LoginSignup
15
6

More than 5 years have passed since last update.

javascriptで現在実行中のファイルパス(__FILE__)及び行番号(__LINE__)を取得する方法

Last updated at Posted at 2017-02-10

注: arguments.callee はstrict mode では使えず、Error.prototype.stack は標準化から外れています。あくまでデバック目的にだけ利用し、一般公開するソースコードには含めないことを推奨します。また、__FILE__ はURLから生成しており、サーバに存在するファイルパスとは異なることがあります。

Object.defineProperty(window, '__STACK__', {
    get: function(){
        let origin = Error.prepareStackTrace;
        Error.prepareStackTrace = function(_, stack){ return stack; };
        let err = new Error;
        Error.captureStackTrace(err, arguments.callee);
        let stack = err.stack;
        Error.prepareStackTrace = origin;
        return stack;
    }
});
Object.defineProperty(window, '__FILE__', {
    get: function(){
        let filename = __STACK__[1].getFileName().replace(location.origin, "").replace(window.location.search, "");
        if(!filename) filename = "/";
        return filename;
    }
});
Object.defineProperty(window, '__LINE__', {
    get: function(){
        return __STACK__[1].getLineNumber();
    }
});
console.log("__FILE__", __FILE__);
console.log("__LINE__", __LINE__);

jQueryの $.ajax() ( $().load(), $.get(), $.getScript() なども $.ajax()のラッパーなのでこれに含まれる) で外部ファイルを読み込んだ場合、 xmlHttpRequest による読み込みなのでデフォルトではファイル名が取得されない(Chrome のconsole で試すと、VM上に展開されているのがわかる)。従って__FILE__ は使えない(__LINE__ は使える)。その為これらを使いたい場合は、上記とは別に工夫する必要がある。

まず、読み込み元のファイルに以下を記述する。

$.ajaxSetup({
    dataFilter: function(data) {
        let filename = this.url.replace(location.origin, "").replace(/\?.*/, "");
        if(this.dataType === "script") return `__XHR_FILE__ = "${filename}";\n` + data;
        else if(this.dataType === "html") return `<script class="init_script">__XHR_FILE__ = "${filename}";<\/script>` + data;
        else return data;
    },
});

こうすれば、(dataType が "script" と "html" のとき限定だが) __XHR_FILE__ に現在のファイルパスが代入される。あとは読み込み先のファイルで __XHR_FILE__ を参照するだけ。

注意点として、javascript は非同期でファイル読み込みを行っているので、あるファイル内で __XHR_FILE__が代入された後、別のファイルの読み込みが起こり __XHR_FILE__ の値が置き換わる可能性がある。細かくは試してないが、ファイルの最初の行で let xml_file = __XHR_FILE__; のように値をコピーしておけば問題ないだろう。

15
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
6