简体   繁体   English

恢复console.log()

[英]Restoring console.log()

For some reason, the prototype framework (or another JavaScript code) that is shipped with Magento is replacing standard console functions, so I can't debug anything. 出于某种原因, Magento附带的原型框架(或其他JavaScript代码)正在取代标准的控制台功能,所以我无法调试任何东西。 Writing down in JavaScript console console I get the following output: 在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 () {}

I'm using Google Chrome version 13.0.782.112 on Linux. 我在Linux上使用Google Chrome version 13.0.782.112

Prototype JavaScript framework, version 1.6.0.3

Is there a quick way to solve this? 有没有快速解决方法?

Since original console is in window.console object, try restoring window.console from iframe : 由于原始控制台位于window.console对象中,请尝试从iframe恢复window.console

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);

Works for me on Chrome 14. 适用于Chrome 14。

For example, 例如,

delete console.log

would also restore console.log : 还会恢复console.log

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

delete console.log;
console.log;         // function log() { [native code] }

Magento has the following code in /js/varien/js.js - comment it out & it will work. 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() {}
}

delete window.console restores the original console object in Firefox and Chrome. delete window.console恢复Firefox和Chrome中的原始console对象。

How does this work? 这是如何运作的? window is a hosted object and usually it is implemented with a common prototype between all instances (you have many tabs in the browser). window是一个托管对象,通常它是在所有实例之间使用通用原型实现的(浏览器中有很多选项卡)。

Some dumb developers of external libraries/frameworks (or Firebug , etc.) override property console of the window instance, but it doesn't corrupt window.prototype . 外部库/框架(或Firebug等)的一些愚蠢的开发人员覆盖window实例的属性控制台,但它不会破坏window.prototype By the delete operator we are back dispatching from the console.* methods to prototype code. 通过delete运算符,我们将从console.*调用console.*方法到原型代码。

Save a reference to the original console in a variable at the very start of the script and then either use this reference, or redefine console to point to the captured value. 在脚本开头的变量中保存对原始console引用,然后使用此引用,或重新定义console以指向捕获的值。

Example: 例:

var c = window.console;

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

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

// logs to the console
c.log("hello");

Just in case that someone face this same situation. 以防有人面对同样的情况。 I did not replied to the original answer for Xaerxess because I don't have enough reputation to do it. 我没有回复Xaerxess的原始答案,因为我没有足够的声誉去做。 Looks like that is the correct answer, but for some reason I notice sometimes it works in my software and sometimes not... 看起来这是正确的答案,但出于某种原因,我注意到它有时在我的软件中有效,有时不...

So I tried completing deleting before running the script and looks like everything is working fine 100% of times. 所以我尝试在运行脚本之前完成删除,看起来一切都在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; } 

Thank you to everybody. 谢谢大家。

The solutions given in this question no longer solve this problem correctly in new browsers. 此问题中给出的解决方案不再能在新浏览器中正确解决此问题。 The only one that (sort of) work is grasping the console from an <iframe> as told by @Xaerxess. 唯一一个(有点)工作是从@Xaerxess告诉的<iframe>抓住控制台。

I wrote an userscript that protects console from being overwritten. 我写了一个用户脚本来保护控制台不被覆盖。 It doesn't break any tools that override the console - it calls both the overridden and original methods. 它不会破坏任何覆盖控制台的工具 - 它会调用重写和原始方法。 It can of course also be included in web-page. 它当然也可以包含在网页中。

// ==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;
        },
    });
}
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
}

Tested on Chrome 71 and Firefox 65 在Chrome 71和Firefox 65上测试过

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM