Восстановление console.log () - PullRequest
       10

Восстановление console.log ()

45 голосов
/ 17 августа 2011

По какой-то причине прототип (или другой код JavaScript), поставляемый с Magento , заменяет стандартные функции консоли, поэтому я не могу ничего отлаживать. Записывая в консоль JavaScript console, я получаю следующий вывод:

> console
Object
assert: function () {}
count: function () {}
debug: function () {}
dir: function () {}
dirxml: function () {}
error: function () {}
group: function () {}
groupEnd: function () {}
info: function () {}
log: function () {}
profile: function () {}
profileEnd: function () {}
time: function () {}
timeEnd: function () {}
trace: function () {}
warn: function () {}

Я использую Google Chrome version 13.0.782.112 в Linux.

Prototype JavaScript framework, version 1.6.0.3

Есть ли быстрый способ решить эту проблему?

Ответы [ 8 ]

62 голосов
/ 17 августа 2011

Поскольку исходная консоль находится в объекте window.console, попробуйте восстановить window.console из iframe:

var i = document.createElement('iframe');
i.style.display = 'none';
document.body.appendChild(i);
window.console = i.contentWindow.console;
// with Chrome 60+ don't remove the child node
// i.parentNode.removeChild(i);

У меня работает на Chrome 14.

42 голосов
/ 17 августа 2011

Например,

delete console.log

также восстановит console.log:

console.log = null;
console.log;         // null

delete console.log;
console.log;         // function log() { [native code] }
12 голосов
/ 22 февраля 2012

Magento имеет следующий код в /js/varien/js.js - закомментируйте его, и он будет работать.

if (!("console" in window) || !("firebug" in console))
{
    var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
    "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];

    window.console = {};
    for (var i = 0; i < names.length; ++i)
        window.console[names[i]] = function() {}
}
7 голосов
/ 05 декабря 2013

delete window.console восстанавливает исходный console объект в Firefox и Chrome.

Как это работает? window - это размещенный объект, и обычно он реализован с общим прототипом для всех экземпляров (в браузере много вкладок).

Некоторые тупые разработчики внешних библиотек / каркасов (или Firebug и т. Д.) Переопределяют консоль свойств экземпляра window, но не повреждают window.prototype. С помощью оператора delete мы возвращаемся от методов console.* к прототипу кода.

3 голосов
/ 17 августа 2011

Сохраните ссылку на исходный console в переменной в самом начале скрипта, а затем либо используйте эту ссылку, либо переопределите console, чтобы указать на захваченное значение.

Пример:

var c = window.console;

window.console = {
    log :function(str) {
        alert(str);
    }
}

// alerts hello
console.log("hello");

// logs to the console
c.log("hello");
0 голосов
/ 09 марта 2019

На всякий случай, если кто-то столкнется с такой же ситуацией. Я не ответил на первоначальный ответ для Xaerxess, потому что у меня недостаточно репутации, чтобы сделать это. Похоже, это правильный ответ, но по какой-то причине я замечаю, что иногда это работает в моем программном обеспечении, а иногда нет ...

Поэтому я попытался завершить удаление перед запуском скрипта и похоже, что все работает нормально 100% раз.

if (!("console" in window) || !("firebug" in console))
{

  console.log = null;
  console.log;         // null

  delete console.log;

  // Original by Xaerxess
  var i = document.createElement('iframe');
  i.style.display = 'none';
  document.body.appendChild(i);
  window.console = i.contentWindow.console;

}

Спасибо всем.

0 голосов
/ 20 ноября 2018
function restoreConsole() {
  // Create an iframe for start a new console session
  var iframe = document.createElement('iframe');
  // Hide iframe
  iframe.style.display = 'none';
  // Inject iframe on body document
  document.body.appendChild(iframe);
  // Reassign the global variable console with the new console session of the iframe 
  console = iframe.contentWindow.console;
  window.console = console;
  // Don't remove the iframe or console session will be closed
}

Проверено на Chrome 71 и Firefox 65

0 голосов
/ 24 ноября 2017

Решения, приведенные в этом вопросе, больше не решают эту проблему правильно в новых браузерах.Единственное, что (вроде) работает, это захват консоли от <iframe>, как сказал @ Xaerxess.

Я написал скрипт пользователя, который защищает консоль от перезаписи.Он не ломает никакие инструменты, которые переопределяют консоль - он вызывает как переопределенные, так и оригинальные методы.Конечно, он также может быть включен в веб-страницу.

// ==UserScript==
// @name        Protect console
// @namespace   util
// @description Protect console methods from being overriden
// @include     *
// @version     1
// @grant       none
// @run-at      document-start
// ==/UserScript==
{

    /**
      * This object contains new methods assigned to console.
      * @type {{[x:string]:Function}} **/
    const consoleOverridenValues = {};
    /**
      * This object contains original methods copied from the console object
      * @type {{[x:string]:Function}} **/
    const originalConsole = {};
    window.originalConsole = originalConsole;
    // This is the original console object taken from window object
    const originalConsoleObject = console;
    /**
     * 
     * @param {string} name
     */
    function protectConsoleEntry(name) {
        const protectorSetter = function (newValue) {
            originalConsole.warn("Someone tried to change console." + name + " to ", newValue);
            consoleOverridenValues[name] = function () {
                /// call original console first
                originalConsole[name].apply(originalConsoleObject, arguments);
                if (typeof newValue == "function") {
                    /// call inherited console
                    newValue.apply(window.console, arguments);
                }
            }
        }
        const getter = function () {
            if (consoleOverridenValues[name])
                return consoleOverridenValues[name];
            else
                return originalConsole[name];
        }
        Object.defineProperty(console, name, {
            enumerable: true,
            configurable: false,
            get: getter,
            set: protectorSetter
        });
    }

    /*
     *** This section contains window.console protection
     *** It mirrors any properties of newly assigned values
     *** to the overridenConsoleValues
     *** so that they can be used properly
    */

    /** 
      * This is any new object assigned to window.console
      * @type {Object} **/
    var consoleOverridenObject = null;
    /// Separate boolean is used instead
    /// of checking consoleOverridenObject == null
    /// This allows null and undefined to be assigned with 
    /// expected result
    var consoleIsOverriden = false;

    for (var i in console) {
        originalConsole[i] = console[i];
        protectConsoleEntry(i);
    }

    Object.defineProperty(window, "console", {
        /// always returns the original console object
       /// get: function () { return consoleIsOverriden ? consoleOverridenObject : originalConsoleObject; },
        get: function () { return originalConsoleObject; },
        set: function (val) {
            originalConsole.log("Somebody tried to override window.console. I blocked this attempt."
                + " However the emulation is not perfect in this case because: \n"
                + "     window.console = myObject;\n"
                + "     window.console == myObject\n"
                + "returns false."
            )
            consoleIsOverriden = true;
            consoleOverridenObject = val;

            for (let propertyName in val) {
                consoleOverridenValues[propertyName] = val[propertyName];
            }
            return console;
        },
    });
}
...