10

I am trying to build some sort of logger functionality in javascript. Is there any API for a script to get its own filename?

Factor Mystic
  • 26,279
  • 16
  • 79
  • 95
Manohar
  • 1,270
  • 7
  • 17
  • 28
  • Is this what you're asking? http://stackoverflow.com/questions/984510/what-is-my-script-src-url – Roatin Marth Dec 08 '09 at 15:05
  • No I am just trying to have a logger where I can have timestamp, some string, line number, and the js file name etc. Let me try out the solutions given. – Manohar Dec 09 '09 at 13:02
  • 1
    Possible duplicate of [How may I reference the script tag that loaded the currently-executing script?](http://stackoverflow.com/questions/403967/how-may-i-reference-the-script-tag-that-loaded-the-currently-executing-script) – Stephan Mar 24 '16 at 15:47

6 Answers6

18

This should work: (new Error).fileName

Or you can try this:

var filepath;
(function(){ 
    var scripts = document.getElementsByTagName('script'); 
    filepath = scripts[ scripts.length-1 ].src; 
}());

The second option gives you the path of your script file.

pawel
  • 35,827
  • 7
  • 56
  • 53
  • The second approach will conflict with some services like Google Analytics, or New Relic, because they add a script at the end! – sumid Jul 23 '13 at 18:25
  • @sumid, could you explain? – pawel Jul 24 '13 at 08:21
  • @pawel the problem is in the position `[scripts.length-1]`. You assume that your script is the **last** in `scripts`. This is not true when there is some service which adds some scripting afterwards. Then you don't get src of your script but src of the added script which would be typically null. – sumid Jul 24 '13 at 20:51
  • 3
    I know for sure it's the last one at the moment of execution. Scripts are interpreted synchronously while the document is parsed, the `(function(){}())` construct means it's executed immediately, and the script being executed at this very moment is the last one in the DOM, as nothing after it hasn't been parsed yet. However, and maybe I should edit my answer to reflect that, this won't work using deferred/asynchronously loaded ` – pawel Jul 24 '13 at 21:14
  • Ok, sorry, my mistake. Probably I had some problems with async. In the end I used the hard-coded way as stated in the response above. – sumid Jul 25 '13 at 00:40
8

If we can get the current script's tag, then we can read its src attribute. Excerpt from https://stackoverflow.com/a/22745553/4396817 below:

document.currentScript will return the element whose script is currently being processed.

<script>
  var me = document.currentScript;
</script>

Benefits

  • Simple and explicit. Reliable.
  • Don't need to modify the script tag
  • Works with asynchronous scripts (defer & async)
  • Works with scripts inserted dynamically

Problems

  • Will not work in older browsers and IE.

...So from there, we can simply read the src attribute!

<script src="http://website.com/js/script.js">
  alert(document.currentScript.src);
</script>

// Alerts "http://website.com/js/script.js"
Community
  • 1
  • 1
Sheffie
  • 315
  • 3
  • 12
  • 1
    To the casual reader, help the feature reported here monitored on http://caniuse.com. Upvote here: http://github.com/Fyrd/caniuse/issues/1099. – Stephan Mar 24 '16 at 15:49
6

I see two ways:

  • put into every JS file a variable var filename = 'script.js';
  • get the filename using <script> tag name

JS can not get filename like bash/perl/c scripts.

hsz
  • 148,279
  • 62
  • 259
  • 315
  • 1
    *"put into every JS file a variable `var filename = 'script.js';`"* But not at global scope, because the last-loaded one will win. So if you have `a.js` and `b.js` and load them both, and call a function in `a`, it will be tricked into thinking it's `b`. – T.J. Crowder Oct 22 '18 at 15:30
0

Unfortunately this is not possible.

If you change your approach, getting function names may help you which is sometimes possible. Your best chance would be extracting function name from "arguments.callee". This only works if function is defined like

function FN() { ... }

And does not work when

var FN = function() { ... }
dereli
  • 1,814
  • 15
  • 23
0

this is my modification that fixes a few possible issues, but adds a requirement.

It needs you to name the file in a certain way, so for example if you have a .js file, but you want to know which version is loaded (for example to tell a php server). so your js file would be "zoom_v34.js".

    var version;
    (function(){
        var scripts = document.getElementsByTagName('script');
        for (var i=0; i<scripts.length; i++) {
            var start = scripts[i].src.indexOf('zoom_');
            if (start != -1) { var end = scripts[i].src.indexOf('.',start); version = scripts[i].src.substr(start+6,end-start-6); break; }
        }
    }());
    post='login{JS:'+version+'}';
Smellymoo
  • 97
  • 7
  • This probably isn't the best solution, especially since [there appears to be a better one already](http://stackoverflow.com/a/710996/410342) – Shotgun Ninja Sep 29 '15 at 19:46
  • it's not the best solution. it is good when you add the script in different ways, doesn't assume it's the last script, works more reliably with complicated fringe cases, as it enumerates the whole array instead of assuming it's the last. – Smellymoo Oct 01 '15 at 08:06
0

You can try putting this at the top of your JavaScript file:

window.myJSFilename = "";
window.onerror = function(message, url, line) {
    if (window.myJSFilename != "") return;
    window.myJSFilename =  url;
}
throw 1;

Make sure you have only functions below this. The myJSFilename global variable will contain the full path of the JavaScript file, and the filename can be parsed from that. Tested in IE11, but it should work elsewhere.