How to know all the JS file dependencies using JS code? - javascript

My main use-case is to know all the JS file dependencies!
If I have file a.js that define a function foo, and another file b.js that call the function foo, I want to know that b.js -> a.js where -> means that b.js depend on a.js.
Is it possible? Can someone think of a tricky solution for that?
I have tried to override the foo function and get the stack call, and it works fine, I know that b.js call foo, but I still do not know that foo was defined in a.js...
So maybe someone can think of a solution for this:
I have a file named "a.js" that define a global function foo.
And, I have a file named "b.js" that includes code that gets all the non-native functions on the window object, so here I got the global function foo.
Now, for each non-native global functions, I want to know the JS file name that defines them, so here for foo I want to get "a.js"
Is it possible? Can someone think of a tricky solution for that?
Note: I need to run it in the browser, Not using Node.js. And, not all the file are mine, so I can't edit them.

Run this code first, and check the call stack in debugger.
Object.defineProperty(window, 'foo', {
set: function() {
debugger;
}
});

Related

Can I require a function in node.js without executing the entire required file?

This is the first time I ask a question here. I have the following example case:
The export.js file contains a function and some extra lines of code. In this case, it's just a log:
//exporting.js
function add(a,b) {
return a+b;
}
console.log(add(5,8));
module.exports = add;
The import.js file requires the function add, but when it's executed it also prints the log in exporting.js
//import.js
adds = require('./exporting.js');
console.log(adds(1,2));
So it finally prints:
13
3
I want to know if there's a way to require a function without executing all the required file.
I've tried placing my function inside an object, but it still prints the first log.
I hope you can help me, I haven't find anything related, sorry if it's a noob question.
I want to know if there's a way to require a function without executing all the required file.
No, you cannot. With CommonJS modules, the only way you know what is exported is by running the file and letting it assign things to module.exports. Without running the file, there would be nothing exported.
The design solution for this would be to move the exported function you want into a separate module by itself where that module does nothing except export your function. Then, you can require() that module without any side effects of loading the module.

Difference of module definitions using requireJS

requireJS is giving me a headache atm. requireJS is AMD which by definition says it's asynchronous. Normally I would define a module like this.
define("some Name", ["./moduleOne"],function(moduleOne){
//this would be undefined
moduleOne.whatEver();
var aMethod = function(){
//user aModule.whatever();
}
return {
method: aMethod;
}
});
Ok, I got that I can't directly use moduelOne.whatever because it is loaded asynchronous and it's not there if the callback is being called.
First Question, is this correct?
Now if I change the module definition to this:
define("some Name", function(require, exports){
var moduleOne = require(".moduleOne");
//this is OK
moduleOne.whatEver();
var aMethod = function(){
//user aModule.whatever();
}
exports.method = aMethod;
});
I can use aModule.whatever directly. As I read from the docs, using this (commonJS) style, requires parses the function with Function.prototype.toString, sees the require statement and load the modules directly.
I am pretty sure, I am misunderstanding something here and it would be nice of someone could explain how exactly requireJS works and if the second style is really synchronous.
Thanks
You've misunderstood how it works.
In both examples you give in your question the sequence of execution is:
Something requires the module named some_Name. (I don't think RequireJS is happy with module names that have spaces so I'm assuming a module name with an underscore.)
RequireJS looks for the dependencies and the factory function for the module some_Name. The factory is the function given to define when you define the module.
a. If it happens that define("some_Name"... was called before this step, then RequireJS just gets the dependencies and factory function that was given to define.
b. If define("some_Name"... has not been executed yet, RequireJS will go to the network and attempt to fetch a file that contains the define call and execute it. By convention this will be a file with the same name as the module name + the .js extension, but this can be overridden in RequireJS' configuration.
RequireJS checks whether the dependencies are loaded. If not, then it issues require calls for each dependency that is not loaded yet.
RequireJS calls the factory function with the resolved dependencies.
Note that I did not go over all possible scenarios here. I'm sticking with the most common cases to keep things simple.
So...
Ok, I got that I can't directly use moduelOne.whatever because it is loaded asynchronous and it's not there if the callback is being called.
First Question, is this correct?
No, this is not correct. By the time moduleOne.whatEver(); executes, the module moduleOne must have been loaded already. If moduleOne is undefined this is not because of RequireJS' asynchronous nature but because there is a bug in how moduleOne is defined. For instance, if it exports the value undefined, then moduleOne will be undefined. Or you may get an undefined value for moduleOne.whatEver which will then cause an error when you try to call it, but this would be caused by, for instance, forgetting to export whatEver.
The difference between the 2nd case and the first is that the 2nd uses the CommonJS sugar syntax and this causes step 2 above to have a bit of additional processing. Before RequireJS executes the factory it parses the function (as you mentioned) and then processes the factory function as if the defined had been called like this:
define("some_Name", ['require', 'exports', './moduleOne'], function (require, exports) {
The require and exports modules are special modules defined internally by RequireJS. Note how RequireJS adds ./moduleOne at the end of the list of dependencies. Once this is done, the process is exactly the same as for the 1st case.
By the time var moduleOne = require("./moduleOne"); is executed, the module has already been loaded. So what this line does is merely return a reference to the module.

Javascript self execution function query

I was going through some github library wherein I came across the following lines:
//Util.js
(function(exports,global){
global["true"] = exports;
"use strict";
...rest of the code here
})({}, function() {
return this;
}());
The above file was directly included in index.html.
I am aware of the concept of self-executing functions in JS. But what purpose could the above provide ?
The script is referencing the global 'this' to hold a property called 'true' that contains an an object called 'exports' which you probably already figured out. This script appears to be one that initializes some functionality.
My guess as to WHY they are doing it this way is because they are anticipating that 'this' might not just be run in a browser (probably for injecting mocks when unit testing for example) and so it is a way to abstract the global object.
The 'exports' and 'global' parameters are only mentioned as arguments and when setting the property global["true"] in your script. This is why I think it is an initializing script and the exports variable will be used later on by other related scripts. These related scripts which might also be under test (or whatever) and so their global object might be the same as this one.

jsHint "myFunction is defined but never used"

I am reviewing my javascript with JsHint, and it always returns an error, saying that a function is never used. Well, this is not entirely true.
I am integrating my javascript on the project index by external link (<script src="myJs.js"></script>), and on the index I call the functions I have on the myJs.js file after the actual file link. So it all looks like this:
<script src="myJs.js"></script>
<script>
myFunction();
</script>
The reason why I call my functions on the actual document and not in the myJs.js file is because I need some PHP functions running in it, and I need to call them from my index file.
The problem here is that JsHint returns a harmful, but annoying error, saying that "myFunction is defined but never used". Is it not aware that my function can later be called within my index? How can I solve this? Should I simply ignore it?
At the top of myJs.js you could try adding an exported declaration with your function name, something like this.
/* exported myFunction */
This should silence your warning.

The best way to track method invocation in Javascript

I am a beginner in JavaScript, and I am now given a project that used Javascript heavily. In most of the JS files, it will contain statements of the following format:
Jebber.Ajax.enqueueAction(smsType, true, options, callback);
I am familiar with Java, so I assume there might be some import or sth. at the top of the file, but there isn't any, and there is no explicit definition of "Jebber" variable. So I am curious about where does this Jebber variable come from. I am using Eclipse to edit the JavaScript files, it seems F3 doesn't work to retrieve the definition of a method.
So I am a little bit stuck here:could experts teach me a good way to dive through a large collection of JavaScript files to find the definition of variables/functions etc.? Thanks in advance.
You can do that using JS Object setters:
Object.defineProperty(window, 'Jebber', {
set: function() {
debugger;
},
get: function() {}
});
When something is assigned to a global Jebber variable you'll get a break in a js debugger (use the one in chrome dev tools for example)
Live demo: http://jsfiddle.net/XtZkJ/
Open debugger and see on the stack trace - it will point to the exact line the variable modified.
The "import" will be <script> tags within the HTML file, not the script file.

Categories