Is there a way to work-around site(s) breaking con

2019-06-04 19:02发布

问题:

Excerpt of my Chrome DevTools Console:

Navigated to https://twitter.com/
console.log.toString();
"function (){}"
Navigated to http://linuxfr.org/
console.log.toString();
"function log() { [native code] }"

I managed to inject code in the main frame of twitter.com, using a Chrome Extension, but I had a hard time understanding why my code seemed to not run. It appears that my code is running fine, except console.log produces exactly nothing!

Question: is there a way to call the "now gone" console.log "native code"?

(remarks about that kind of JavaScript "WAT" behavior retracted, sort of)

回答1:

As this is a Chrome Extension, you set your content script to run_at: "document_start" - you can(theoretically) "grab" console.log / error / dir / info etc before twitter gets it's grubby hands on them

actually, KNOWING that twitter only replaces log, warn, info, error, you can simply do:

var _console = ['log', 'warn', 'info', 'error'].reduce(function(result, key) { 
    result[key] = console[key].bind(console); 
    return result
}, {});

then you can use _console.log and friends



回答2:

As far as I know, it depends on how deep replacement was done. For example if it was like this

 console.log = function () {};

The original native log function is still in prototype. You can access it using __proto__ property or Object.getPrototypeOf method.

console.log = null
Object.getPrototypeOf(console).log
//log() { [native code] }

Also you can just delete replacement from original console object

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

But all above code won't work if I replace log function like this

console.__proto__.__proto__.log = function () {}

And unfortunately I don't know workaround for this case.



回答3:

Based on the discussion above and @JaromandaX and JavaScript: The Definitive Guide below is one simple polyfill.

function log() {
    if (location.hostname === 'twitter.com'){
        Object.getPrototypeOf(console).log.apply(console, arguments);
    } else {
        console.log.apply(console, arguments);
    }
}