How to know what variables and functions are defined by script files? - javascript

I have to know what variables and functions are defined by a script file.
I have to use it in scenario where,I'm using cdn to load first,if it fails the variables and functions will not be defined, so i will load the script file from local.
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.4.1/core.min.js"></script>
<script>
if (typeof ($.Core) == 'undefined') {
// local script source
}
</script>

$ is the jquery object, so that wouldn't make any sense.
You want to look in the source file at the bottom to see what it defines. This is obviously going to be very hard on a minified file so start by getting the non-minified version. So change the url to be '.js' instead of '.min.js' (and paste that into your browser adress bar to download the non-minified version).
If you are out of luck and a non-minified version isn't available, try the 'beautifyjs' service.
At the bottom of the file we find
// CommonJS export
if(typeof module != 'undefined' && module.exports)module.exports = __e;
// RequireJS export
else if(typeof define == 'function' && define.amd)define(function(){return __e});
// Export to global object
else __g.core = __e;
We are looking for the //Export to global object in this case, and we find they called it core
So you want to test for typeof (core) == 'undefined'

Related

Uncaught ReferenceError: $ is not defined, but jQuery is called before script

I'm stumped. I'm working on building an Adobe Illustrator panel (based on Adobe CEP) and I cannot figure out why I'm getting an uncaught reference error: $ is not defined. I have my jQuery script linked before my .js file. To my knowledge, I need to use a local copy of jQuery so that it can be bundled with the other files to be deployed as an extension.
Here is an excerpt of my index.html and panel.js files:
I have my script links at the footer of my html (no script is being called within the HTML).
</div>
<script src="assets/js/jquery.min.js"></script>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/CSInterface.js"></script>
<script src="assets/js/panel.js"></script>
</body>
</html>
// panel.js
var csi = new CSInterface(); // Adobe CEP
$(btnAddRegistration).on("click", function (e) { // Errors here
// more code here
}
Console: Uncaught ReferenceError: $ is not defined (panel.js:10) (It says line 10 because there are additional lines of comments at the top of the document).
I appreciate any advice or help figuring this one out. Thank you for your time!
I've tried moving my jQuery code into a document ready and window onload block, but no luck.
"window.onload = function() {
//code here
};
$(document).ready(function () {
//your code here
});
I re-downloaded my jquery.min.js file to make sure it wasn't corrupted. I've also tried moving the script src to the header section of my HTML and no change.
I searched through the Adobe CEP documentation and adding the line below above my scripts fixed the issue.
<script>if (typeof module === 'object') { window.module = module; module = undefined; }</script>
<script>if (typeof exports === 'object') { window.exports = exports; exports = undefined; }</script>
Excerpt from the documentation:
JQuery startup code
if ( typeof module === "object" && typeof module.exports === "object" ) {
// set jQuery in `module`
} else {
// set jQuery in `window`
}
When this code is executed in CEP's browser with nodejs enabled, it will make JQuery to load in module context instead of Browser context. This would cause issues to extension's startup. Please use below code to handle such scenarios:
global symbols handling
<!-- Insert this line above script imports -->
<script>if (typeof module === 'object') {window.module = module; module = undefined;}</script>
<script>if (typeof exports === 'object') {window.exports = exports; exports = undefined;}</script>
<!-- extension's imports -->
<script src="scripts/jquery.min.js"></script>
<script src="scripts/csinterface.js"></script>
<!-- Insert this line after script imports -->
<script>if (window.module) module = window.module;</script>
<script>if (window.exports) exports = window.exports;</script>
If you are not using "module" and "exports" in the extension, you could skip last 2 lines of above code. This logic is similar to how users handled nodejs's require while importing. If you are handling require already, you should continue to handle same way.
You have to actually assign $ to the variable jQuery. Try to wrap your entire code in the following IIFE:
( function( $ ) {
// all your code here:
// panel.js
var csi = new CSInterface(); // Adobe CEP
$(btnAddRegistration).on("click", function (e) { }
// end of your code
} )( jQuery );
Purpose of this anonymous closure:
map $ to jQuery
Variables and methods declared inside this function will not be visible outside of it.
What is an IIFE: https://developer.mozilla.org/en-US/docs/Glossary/IIFE

Implementing require in the absence of node

Modules generally start something like this
(function(root, factory)
{
/* globals define */
if (typeof define === 'function' && define.amd)
{
// AMD. Register as an anonymous module.
define([], factory);
}
else if (typeof module === 'object' && typeof exports !== 'undefined')
{
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory();
}
else
{
// Browser globals (root is window)
root.Papa = factory();
}
I'm trying to implement require to handle node style CommonJS-like modules.
Find the package folder, parse package.json to learn the entrypoint and dependencies, recursively descent with a shared cache to load dependencies... that stuff works.
But having loaded the script for a module, I'm having trouble executing it in such a way as to have it populate module.exports
This will all end up running on Jint (a JS interpreter) so node isn't supplying the usual furniture, I have to build it all myself. There's no step-debug with Jint so I'm using node from VS Code and faking Jint like this.
import * as fs from "fs";
var code = fs.readFileSync("node_modules/papaparse/papaparse.js").toString();
let x = 3;
console.log(eval("x*x"))
let result = eval(`
let module = { exports: "dunno" };
${code}
console.log(module.exports);
`);
This is in a file test.js and package.json nominates this file as main and specifies a type of module. It launches, reads the module code, creates module and runs the code, which promptly complains that it Cannot set properties of undefined (setting 'Papa').
Looking at the snippet above, that tells us it's executing the last else clause, which means it's not seeing module. I thought it might be some sort of scope thing for eval which is where this came from
let x = 3;
console.log(eval("x*x"))
but that duly writes 9 to the console so the question is why module isn't in scope.
This is one of those JavaScript closure weirdnesses; can anyone guide me on how to provide the module object so that the second clause will take effect populating module.exports with the result of factory()?
I know I said it's running in the absence of Node, but I'm debugging it using Node mostly because that's what you get when you launch a js file in VS Code. As already mentioned the production target is Jint. The debug environment is as close an approximation as I can manage, and I'm refraining from using facilities that won't be available in production.
In the debug environment I've created a package.json file that governs whether it's treated as CommonJS or ES6. Experiments show that the production environment behaves like more ES6 than commonjs. The trouble is that most packages expect that they will run either in a browser or in node. They don't consider the possibility of another headless environment. The code above decides it's browser hosted and tries to to install Papa in a DOM that isn't there.
The solution is to wrap the module like so (I'm constructing a string in C#).
string wrapped =
#"(function () {
var module = { exports: { } }; " +
jsSource + #"
var strays = Object.keys(this).filter(itemName => itemName !== 'module');
if (strays.length === 1)
module.exports = this[strays[0]]
else
strays.forEach(itemName => module.exports[itemName] = this[itemName]);
return module.exports;
}).apply({});";
Wrapping it in an anonymous function and using apply to set this for the call allows the "DOM write" to succeed, and a little follow-up code looks for these strays, gathering them up into module exports before returning to normal operation.

Prevent bundling jQuery as a dependency with Browserify

So I have been searching all over the internet to try to find a solution to this problem but I cannot find a solution that works. I'm currently using the latest version of Gulp and Browserify to bundle up JS for the website I'm working on. We previously would concatenate all the JS files together, but I'm moving to a module setup now.
The problem I am running into is duplicating certain dependencies, in this example, I'll focus on jQuery (v2.1.4). Here is my setup:
main.js (Loaded on every page)
window.jQuery = window.$ = require('jquery');
window.Vue = require('vue');
require('jquery-validation');
// More JS that loads on all pages
page.js (Each page has it's own js file for scripts relating to that page)
require('remodal'); // This requires jQuery
// Rest of the JS for this page...
The problem I am running into is that now jQuery is in both javascript bundles. With Browserify, I marked jQuery as "external" for page-speicific.js which removed jQuery from the script, but I get an error Uncaught Error: Cannot find module 'jquery' and I cannot seem to find a solution to this.
If I "exclude" jQuery with Browserify, or if I put a try block around the require('remodal'), I end up with Uncaught TypeError: $(...).remodal is not a function instead. I'm guessing since the module remodal requires jQuery and it's not loaded there, it's not seeing it's set to the window and that's why execution fails?
Well, found the answer to my question. Guess a night of rest was all I needed to be able to think clearer to search for an answer.
I checked out browserify-shim (and browserify-global-shim) at some point, but found that it would only shim top-level dependencies. If jQuery was a dependency of a dependency, this would not work. Well, once I found the answer linked below, I discovered that theres an undocumented (at least, I never found it) { global: true } you can set to have the shim propagate to all dependencies.
var b = browserify();
var globalShim = require('browserify-global-shim').configure({
'jquery': '$'
});
b.transform({ global: true }, globalShim);
After running gulp, all of my page-specific scripts now referenced jQuery as a window variable.
!(function(root, factory) {
if (typeof define === 'function' && define.amd) {
define(['jquery'], function($) {
return factory(root, $);
});
} else if (typeof exports === 'object') {
factory(root, (window.$)); // <----------------- :D
} else {
factory(root, root.jQuery || root.Zepto);
}
})(this, function(global, $) {
Source: Shimming dependencies of dependencies with browserify-shim

Unable to load module that uses a named define call

I am using RequireJS & its working fine for some modules. Recently, I added two test modules (code for the modules seems to be fine). I am importing them in my main (javascript) file and I can see that the file get imported in the browser. However, I see the following error message and I cannot troubleshoot properly what might be causing this issue. Any suggestions to fix or troubleshoot this will be greatly appreciated.
Error Message in browser
Error: No define call for urlCore/urlTest http://requirejs.org/docs/errors.html#nodefine
...{c=c[b]});return c}function C(b,c,d,g){c=Error(c+"\nhttp://requirejs.org/docs/er...
module to be imported:
define("urlTest", [], function() { //no dependencies on other modules
'use strict';
var urlTest = function() {
this.getTestURL = function(url, urlChk) {
if (typeof url === 'undefined' || typeof urlChk === 'undefined' ||
url === '' || urlChk === '') { //we can check length instead as well || removing typeof does not solve the issue
throw new Error("urlCommon - url or urlChk values are invalid:" + url + "|" + urlChk);
}
if (url !== null && url.length > 0 && urlChk === "Y") {
return url;
}
}; //end of getTestURL
urlTest.version = '0.0.1';
};
return urlTest;
});
I tried this but it does not work either:
/*
define("urlTest", [], function() { //no dependencies on other modules
'use strict';
return {
getTestURL : function(url, urlChk) {
if (url !== null && url.length > 0 && urlChk === "Y") {
return url;
}
}
} //end return
}); //end test module
*/
Main.js paths:
paths: {
//"jquery": "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min"
'validateTest': 'validation/validateTest', //works
'normalizedXHR': 'xhr/normalizedXHR', //works
'urlTest': 'urlCore/urlTest', //does not work
'jsonTest': 'json/jsonTest' //does not work
}
Update:
I am using the urlTest from this module:
define('testResponse', ['./urlCore/urlTest', './json/jsonTest'], function(urlTest, jsonTest) {
'use strict';
Another Update
When I set enforceDefine to true with waitSeconds to a value greater than 0, I receive the following error (even though I see the JS file being loaded in the browser):
Error: Load timeout for modules: urlCore/urlTest
This urlTest is a dependency in a module (which sits in another directory). When I try the following, the dependencies do not load up in the browser:
define('testResponse', ['../urlCore/urlTest'], function(urlTest) {
When I try the following, the file appears to load in the browser window but I get the requirejs error stating a load timeout for module error.
define('testResponse', ['./urlCore/urlTest'], function(urlTest) {
File structure:
javascripts
javascripts/main.js
javascripts/abc/testResponse.js
javascripts/urlCore/urlTest.js
Another Update
I am able to call other modules residing in a separate directory. The issue comes forward when one of the modules in those directories e.g. abc/testResponse has a dependency on urlCore/urlTest. This appears to cause the issue for me. Should I be specifying the config part in this module as well in addition to the main.js (I'm not doing that right now).
define('testResponse', ['./urlCore/urlTest'], function(urlTest) {
When I try the ../urlCore/urlTest, the file does not event load up.
Judging by what you are showing in the question, urlTest is loaded with the path urlCore/urlTest and at this path there is a file which contains this:
define("urlTest", [], function() {
This works, so long as what RequireJS is loading a module named urlTest. No problem there. However, if you require any other module name that ultimately resolves to the path urlCore/urlTest, then you are in trouble, because the module name will not correspond to the name that you have in your define call. Or to put it differently, for your module to load when required under the name urlCore/urlTest, the define call in the module's file would have to say:
define("urlCore/urlTest", [], function() {
The easy fix for this is to not assign names to modules in your define calls. Just put the dependencies and the callback and leave the name out.
Even if you use define without specifying a module name, you still have to be careful not to end up loading the same module under two different names, because if you do, you will get a timeout when you try loading with the 2nd name. In the code you show in the question, I'd recommend using urlTest everywhere or using relative paths everywhere to load this module but don't mix the two.

How to use node modules with in UIAutomation

According to apple's documentation I can import one JS file into another with an import statement. And yes I am able to use JS functions and recursively call other JS functions.
But can I include node modules into my automation. Node/npm module seems to have a lot of tools that makes life easier and avoid code duplication.
And actually I was able to use one node module called moment.js through the following call in my code
#import "../node_modules/moment/moment.js"
But I am not have the same luck with other npm modules. I tried couple Faker.js, Charlatan.js and I getting the following error in Faker.js
Script threw an uncaught JavaScript error: Can't find variable: window
on line 618 of Faker.js
Looking at *.js files it looks like it has something to do with the way these modules are packaged. My JS knowledge isn't getting me anywhere.
The last few lines of moment js file
// CommonJS module is defined
if (hasModule) {
module.exports = moment;
}
/*global ender:false */
if (typeof ender === 'undefined') {
// here, `this` means `window` in the browser, or `global` on the server
// add `moment` as a global object via a string identifier,
// for Closure Compiler "advanced" mode
this['moment'] = moment;
}
/*global define:false */
if (typeof define === "function" && define.amd) {
define("moment", [], function () {
return moment;
});
}
Last few lines of Faker js file
if (typeof define == 'function'){
define(function(){
return Faker;
});
}
else if(typeof module !== 'undefined' && module.exports) {
module.exports = Faker;
}
else {
window.Faker = Faker;
}
I am perfectly able to play with these modules in node console, so nothing wrong with the modules, it just how to include/require them in my JS files.
Had to do two things for Faker to work for me
remove 'use strict'
Check if window is undefined
Add this statement
this['Faker'] = Faker;

Categories