Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Трейсинг JS и логирование вызовов (https://javascript.ru/forum/misc/56005-trejjsing-js-i-logirovanie-vyzovov.html)

reinterpret_alexey 25.05.2015 12:44

Трейсинг JS и логирование вызовов
 
Имеется функция на JS, запускающаяся в браузере (т.е. требующая window, window.document и т.п.)
Необходимо проследить какие методы каких объектов вызывал скрипт и какие свойства каких объектов
читал и изменял.

Существуют ли инструменты/отладчики/фреймворки для JS, позволяющие это сделать?

Я пробовал вешать "обработчик" на каждую функцию в window, проходя window рекурсивно (чтобы повесить
обработчики и функции объектов, функции объектов внутри объектов и так далее):

Код:

function augment(withFn) {
    var name, fn;
    for (name in window) {
        fn = window[name];
        if (typeof fn === 'function') {
            window[name] = (function(name, fn) {
                var args = arguments;
                return function() {
                    withFn.apply(this, args);
                    return fn.apply(this, arguments);

                }
            })(name, fn);
        }
    }
}

Но это настолько ресурсорасточительно, что сожрало больше 1 Гб памяти (IE подвесил систему и дальше я его просто убил). Нужен более гуманный способ.

Короче, к примеру, если скрипт делает

window.shit = 'a';
alert(window.shit);

, то в логе должна быть инфа о том, что:


writing window.shit
reading window.shit
calling window.alert


В задаче мне нужно знать, что из "окружения", в котором скрипт работает, он читает и вызывает.

tsigel 26.05.2015 09:35

Мне кажется что в данном случае проще пойти от обратного. Обернуть скрипт в свой scope, в котором будет эмуляция window, document и т.д. Это даст:
Во первых вы сможете отслеживать что происходит (например навесив гетторы и сетторы на все свойства эмуляции window), правда за переменными созданными через var так следить не получится. Ну и если вы сделаете свои эмуляции нерасширяемыми, то по стеку ошибок вы сможете понять что он пытался записать туда.

reinterpret_alexey 26.05.2015 21:31

tsigel,

Вся проблема в том, что в скрипте выполняются миллионы строк. Руками не получится. Нужна именно автоматизация.

kostyanet 27.05.2015 05:23

Вся проблема в том, что нет практического смысла. Особенно логировать присвоение значения сильный ход.

reinterpret_alexey 27.05.2015 09:09

kostyanet,

Практический смысл есть. Соотносящийся с деньгами.
UPD: Логировать read/write нужно только в отношении свойств, которые лежат в window.
Для тех, что создает скрипт в процессе работы - не надо.

kostyanet 27.05.2015 10:22

Напишите свой интерпретатор.

tsigel 27.05.2015 12:10

var handler = {
    get: function(target, name){
        alert('get element with name: ' + name);
        return name in target?
            target[name] : undefined;
    },
    set: function (target, name, value) {
        alert('set element with name: ' + name);
        target[name] = value;
        return target;
    }
};

var p = new Proxy({}, handler);
p.a;
p.b = 3;

Смотреть в ff;
Подмените window таким объектом и наслаждайтесь логами

reinterpret_alexey 28.05.2015 09:16

tsigel,

Thx, но тут есть проблема. Я почитал мануал mozilla по прокси-объектам (https://developer.mozilla.org/ru/doc..._Objects/Proxy) и выяснилось, что вроде бы нельзя никак именно подменить window, можно только создать новый объект - например, window2. А я не могу "заставить" скрипт использовать мой объект вместо window. Скрипт обфусцирован и велик. Мне потому и надо залогировать все вызовы и чтения свойств, что их не видно из-за обфускации (снять - не вариант). Скрипт может где-то в середине обращаться к window, складывая название объекта window по буковкам в разных callback-ах setInterval/setTimeout, и такая жесть есть. Вот в чем дело.

tsigel 28.05.2015 11:06

Цитата:

Сообщение от reinterpret_alexey
tsigel,

Thx, но тут есть проблема. Я почитал мануал mozilla по прокси-объектам (https://developer.mozilla.org/ru/doc..._Objects/Proxy) и выяснилось, что вроде бы нельзя никак именно подменить window, можно только создать новый объект - например, window2. А я не могу "заставить" скрипт использовать мой объект вместо window. Скрипт обфусцирован и велик. Мне потому и надо залогировать все вызовы и чтения свойств, что их не видно из-за обфускации (снять - не вариант). Скрипт может где-то в середине обращаться к window, складывая название объекта window по буковкам в разных callback-ах setInterval/setTimeout, и такая жесть есть. Вот в чем дело.

Можете, и очень просто, для этого достаточно обернуть этот скрипт в свой. Это делается примерно так:

var myWindow = new Proxy({}, {
    get: function(target, name){
        alert('get window element with name: ' + name);
        return name in target?
            target[name] : window[name];
    },
    set: function (target, name, value) {
        alert('set window element with name: ' + name);
        target[name] = value;
        return target;
    }
});
var myDocument = ...;

(function (window, document) {

  // Здесь много вражеского кода, который надо залогировать.

}).call(myWindow, myWindow, myDocument);


Если вы обернете код который хотите прологировать в свою функцию и переопределите там window, то тот код уже никак не доберется до оригинального window (кроме разве что с помощью конструкций типа eval(...) или new Function(...) и таймаут/интервал с о строковым параметром, но их вы можете найти поиском).


Часовой пояс GMT +3, время: 05:46.