How can I find where my object is being frozen? - javascript

I get this error:
Error: You attempted to set the key `TpDeF3wd6UoQ6BjEFmwz` with the value `{"seen":true}` on an object that is meant to be immutable and has been frozen.
How can I discover what code is directly/indirectly freezing my object and making it immutable?
I've solved the error in development by rewriting the logic completely, but I'd like to understand how to debug this type of error.

One idea it to replace Object.freeze with your own that logs the stack, and then calls the old freeze.
Below is an example, you can see it's at 30:8
The line numbers in this snippet don't line up, only because SO snippets will be adding some extra wrapper code, but in production this should give you the correct line no.
'use strict';
function DebugFreeze() {
const oldFree = Object.freeze;
Object.freeze = (...args) => {
console.log(new Error("Object Frozen").stack);
return oldFree.call(Object, ...args);
}
}
DebugFreeze();
const a = { one: 1 };
a.two = 2;
Object.freeze(a);
a.three = 3;
console.log("here");

Related

How to bind console.log to another function call so I can see line number of the script in console where it is called?

My code works but with additional parenthesis like myfunction()();. It should execute with single parenthesis just like normal e.g myfunction();.
I'm building console.time(); console.timeEnd(); polyfill for browsers (e.g <IE10) which do not have native built-in. Note: I have bind() polyfill in-case you think <IE10 does not have it.
Here is my code in "polyfill.js file".
(function() {
'use strict';
var console=window.console, timers={};
if (!console.time) {
console.time = function(name) {
var datenow = Date.now();
name = name? name: 'default';
if (timers[name]) {
console.warn('Timer "'+name+'" already exists.');
}
else timers[name] = datenow;
};
console.timeEnd = function(name) {
var datenow = Date.now();
name = name? name: 'default';
if (!timers[name]) {
console.warn('Timer "'+name+'" does not exists.');
}
else {
var endt = datenow - timers[name];
delete timers[name];
//below is the line where some changes are needed, But I don't know how.
return window.console.log.bind(window.console, name+ ': ' +endt+ 'ms');
}
};
}
}());
Now in another file "main.js file", when I use console.time(); console.timeEnd();, it should log code-line-number of this file in browser console (not the line-number of polyfill.js file). Of-course it works but notice additional parenthesis "()()" below which is not cool.
console.time();
//any code for performance test goes here.
console.timeEnd()(); //Note here "()()". It should be single "()"
I have consulted these 2 stackoverflow questions, but couldn't come up with the right answer.
Wrapping a wrapper of console log with correct file/line number?
A proper wrapper for console.log with correct line number?
I also checked new Error().stack; as an option, but it is also not supported in those browser for which I'm building my polyfill.
Note: If anyone can suggest a solution with eval();, you can. It is also acceptable for me.
There is in fact a function for that called console.trace, which you can read more about in the MDN page.
What it does is print the entire stack trace to the line where it has been called from.
So, for example, running the next code:
function firstFunc() {
secondFunc();
}
function secondFunc() {
console.trace('I was called here!');
}
console.log('Calling firstFunc:');
firstFunc();
will print out this output in the console:
Calling firstFunc:
I was called here!
secondFunc # VM141:6
firstFunc # VM141:2
(anonymous) # VM141:10 // Internal browser trace
Notice that in the given output, all functions are being called and defined in the Chrome console, hence the # VM141:. Generally, it prints the file instead of VM. So, had it been located in an index.js file, it would look like this:
Calling firstFunc:
I was called here!
secondFunc # index.js:8
Compatibility Note
The above method works for any sane browser, and IE11+. That is due to the implementation of console.trace only in IE11.
However, per OP's request, I can think of a creative way to support IE10, and that is by using the Error.prototype.stack property.
Now, of course, as MDN itself mentions it, it's a non-standard feature that should not be used in production, but neither is supporting IE6.
By creating an Error instance and then printing its stack, you can achieve a similar result.
const sumWithTrace = (num1, num2) => {
console.log(new Error().stack); // Creating a new error for its stack property
return num1 + num2;
};
sumWithTrace(1, 5); // returns 6 and prints trace in console

Mock a JavaScript object in production code

I want to mock a JavaScript object in production code so it can be configured to do nothing. The object is quite complex, and has many properties including nested properties along with functions. Accessing any property should not result in a TypeError, and should have no side effects. Running any function name should be a noop. Counter example:
// Naive attempt at resetting the object so it does nothing:
let client = {};
// This will produce a type error:
client.some.nested.prop.here = 10;
// This will produce a type error:
console.log(client.some.nested.prop.here);
// This will also produce a type error:
client.someFunction();
What I have tried so far is using a proxy handler:
const clientHandler = {
set: () => true,
get: () => {
return new Proxy(() => {}, clientHandler);
},
has: () => true,
apply: () => {
console.log('Noop function, mock client used instead.');
},
};
let client = new Proxy({}, clientHandler);
// No type error, code continues working.
client.some.nested.prop.here = 10;
// No type error, code continues working.
console.log(client.some.other.nested.prop);
// Also no type error,
client.does.not.exist.someFunction();
This does work pretty well. So what I am looking for is whether there is a simpler way to do this, or another more idiomatic approach, or really just any approach that might have different pros and cons to the above. Also any improvements to the above approach would be interesting to consider.

How to avoid accidentally implicitly referring to properties on the global object?

Is it possible to execute a block of code without the implicit with(global) context that all scripts seem to have by default? For example, in a browser, would there be any way to set up a script so that a line such as
const foo = location;
throws
Uncaught ReferenceError: location is not defined
instead of accessing window.location, when location has not been declared first? Lacking that, is there a way that such an implicit reference could result in a warning of some sort? It can be a source of bugs when writing code (see below), so having a way to guard against it could be useful.
(Of course, due to ordinary scoping rules, it's possible to declare another variable with the same name using const or let, or within an inner block, to ensure that using that variable name references the new variable rather than the global property, but that's not the same thing.)
This may be similar to asking whether it's possible to stop referencing a property from within an actual with statement:
const obj = { prop: 'prop' };
with (obj) {
// how to make referencing "prop" from somewhere within this block throw a ReferenceError
}
It's known that with should not be used in the first place, but unfortunately it seems we have no choice when it comes to the with(global), which occasionally saves a few characters at the expense of confusing bugs which pop up somewhat frequently: 1 2 3 4 5 6. For example:
var status = false;
if (status) {
console.log('status is actually truthy!');
}
(the issue here: window.status is a reserved property - when assigned to, it coerces the assigned expression to a string)
These sorts of bugs are the same reason that explicit use of with is discouraged or prohibited, yet the implicit with(global) continues to cause issues, even in strict mode, so figuring out a way around it would be useful.
There are some things you need to consider before trying to answer this question.
For example, take the Object constructor. It is a "Standard built-in object".
window.status is part of the Window interface.
Obviously, you don't want status to refer to window.status, but do you want Object to refer to window.Object?
The solution to your problem of it not being able to be redefined is to use a IIFE, or a module, which should be what you are doing anyways.
(() => {
var status = false;
if (!status) {
console.log('status is now false.');
}
})();
And to prevent accidentally using global variables, I would just set up your linter to warn against it. Forcing it using a solution like with (fake_global) would not only have errors exclusively at run time, which might be not caught, but also be slower.
Specifically with ESLint, I can't seem to find a "good" solution. Enabling browser globals allows implicit reads.
I would suggest no-implicit-globals (As you shouldn't be polluting the global scope anyways, and it prevents the var status not defining anything problem), and also not enabling all browser globals, only, say, window, document, console, setInterval, etc., like you said in the comments.
Look at the ESLint environments to see which ones you would like to enable. By default, things like Object and Array are in the global scope, but things like those listed above and atob are not.
To see the exact list of globals, they are defined by this file in ESLint and the globals NPM package. I would would pick from (a combination of) "es6", "worker" or "shared-node-browser".
The eslintrc file would have:
{
"rules": {
"no-implicit-globals": "error"
},
"globals": {
"window": "readonly",
"document": "readonly"
},
"env": {
"browser": false,
"es6": [true/false],
"worker": [true/false],
"shared-node-browser": [true/false]
}
}
If you're not in strict mode, one possibility is to iterate over the property names of the global (or withed) object, and create another object from those properties, whose setters and getters all throw ReferenceErrors, and then nest your code in another with over that object. See comments in the code below.
This isn't a nice solution, but it's the only one I can think of:
const makeObjWhosePropsThrow = inputObj => Object.getOwnPropertyNames(inputObj)
.reduce((a, propName) => {
const doThrow = () => { throw new ReferenceError(propName + ' is not defined!'); };
Object.defineProperty(a, propName, { get: doThrow, set: doThrow });
return a;
}, {});
// (using setTimeout so that console shows both this and the next error)
setTimeout(() => {
const windowWhichThrows = makeObjWhosePropsThrow(window);
with (windowWhichThrows) {
/* Use an IIFE
* so that variables with the same name declared with "var" inside
* create a locally scoped variable
* rather than try to reference the property, which would throw
*/
(() => {
// Declaring any variable name will not throw:
var alert = true; // window.alert
const open = true; // window.open
// Referencing a property name without declaring it first will throw:
const foo = location;
})();
}
});
const obj = { prop1: 'prop1' };
with (obj) {
const inner = makeObjWhosePropsThrow(obj);
with (inner) {
// Referencing a property name without declaring it first will throw:
console.log(prop1);
}
}
.as-console-wrapper {
max-height: 100% !important;
}
Caveats:
This explicitly uses with, which is forbidden in strict mode
This doesn't exactly escape the implicit with(global) scope, or the with(obj) scope: variables in the outer scope with the same name as a property will not be referenceable.
window has a property window, which refers to window. window.window === window. So, referencing window inside the with will throw. Either explicitly exclude the window property, or save another reference to window first.
Somewhat simpler to implement than #CertainPerformance's answer, you can use a Proxy to catch implicit access to everything except window. The only caveat is you can't run this in strict mode:
const strictWindow = Object.create(
new Proxy(window, {
get (target, property) {
if (typeof property !== 'string') return undefined
console.log(`implicit access to ${property}`)
throw new ReferenceError(`${property} is not defined`)
}
}),
Object.getOwnPropertyDescriptors({ window })
)
with (strictWindow) {
try {
const foo = location
} catch (error) {
window.console.log(error.toString())
}
// doesn't throw error
const foo = window.location
}
Notice that even console has to have an explicit reference in order to not throw. If you want to add that as another exception, just modify strictWindow with another own property using
Object.getOwnPropertyDescriptors({ window, console })
In fact, there are a lot of standard built-in objects you may want to add exceptions for, but that is beyond the scope of this answer (no pun intended).
In my opinion, the benefits this offers fall short of the benefits of running in strict mode. A much better solution is to use a properly configured linter that catches implicit references during development rather than at runtime in non-strict mode.
Perhaps slightly cleaner (YMMV) is to set getter traps (like you did), but in a worker so that you don't pollute your main global scope. I didn't need to use with though, so perhaps that is an improvement.
Worker "Thread"
//worker; foo.js
addEventListener('message', function ({ data }) {
try {
eval(`
for (k in self) {
Object.defineProperty(self, k, {
get: function () {
throw new ReferenceError(':(');
}
});
}
// code to execute
${data}
`);
postMessage('no error thrown ');
} catch (e) {
postMessage(`error thrown: ${e.message}`);
}
});
Main "Thread"
var w = new Worker('./foo.js');
w.addEventListener('message', ({data}) => console.log(`response: ${data}`));
w.postMessage('const foo = location');
Another option that may be worth exploring is Puppeteer.
Just use "use strict". More on Strict Mode.

Disabling console access for specific Javascript files

In my current project with lots of dependencies I need a way to disable console access for specific libraries so that those files can't use any of the console functionality.
I could of course disable console functionality by simply finding and replacing it in the library bundle, but as this project has a lot of dependencies that would make updating libraries a huge hassle.
I'm aware that I can disable console functionality by overwriting it with an empty function block:
console.log = function(){};
But that disables the console functionality for the entire project. So im looking for an implementation, or a line of code with which I can disable console functionality for a specific file or code block.
Write a white-listing "middleware" for console.log
// Preserve the old console.log
const log = console.log;
// Used a dictionary because it's faster than lists for lookups
const whiteListedFunctions = {"hello": true};
// Whitelisting "middleware". We used the function's name "funcName"
// as a criteria, but it's adaptable
const isWhitelisted = callerData => callerData.funcName in whiteListedFunctions;
// Replacing the default "console.log"
console.log = arg => {
const stack = new Error().stack.split("at")[2].trim().split(' ');
const fileParts = stack[1].substr(1, stack[1].length - 2).split(':');
const callerData = {
funcName: stack[0],
file: fileParts.slice(0, fileParts.length - 2).join(':'),
lineColNumber: fileParts.slice(fileParts.length - 2).join(':')
};
if (isWhitelisted(callerData)) { // Filtering happens here
log(arg);
}
};
// Define the calling functions
function hello() { console.log("hello"); }
function world() { console.log("world"); }
hello(); // => Prints hello
world(); // => Doesn't print anything
Method explanation
You can do this by creating a whitelist (or blacklist) that will contain your filtering criteria. For example it may contain the name of the functions that call console.log or maybe the file name, or even the line and column numbers.
After that you create your whitelisting "middleware". This will take the caller function data and decide if it can log stuff or not. This will be done based on the previously defined whitelist. You can choose your preferred criteria in this "middleware".
Then you actually replace console.log by overriding with your new logger. This logger will take as an argument the message to log (maybe multiple arguments?). In this function you also need to find the data relating to the caller function (which wanted to call console.log).
Once you have the caller data, you can then use your whitelisting middleware to decide if it can log stuff
Getting information about the caller function
This part is a little "hacky" (but it got the job done in this case). We basically create an Error and check its stack attribute like this new Error().stack. Which will give us this trace
Error
at console.log.arg [as log] (https://stacksnippets.net/js:25:7)
at hello (https://stacksnippets.net/js:41:11)
at https://stacksnippets.net/js:48:1
After processing (split, map, etc...) the trace we get the caller function data. For example here we have
The caller function's name: hello
The file name: https://stacksnippets.net/js
The line and column number: 41:11 (watch out for minifiers)
This bit was inspired by VLAZ's answer in How to disable console.log messages based on criteria from specific javascript source (method, file) or message contents, so make sure to check it out. Really good and thorough post.
Note
To make sense of the trace we can do new Error().stack.split("at")[INDEX].trim().split(' ') where INDEX is the position of the function call you want to target in the stack trace. So if you want to get a different "level" that the one used in this example, try changing INDEX
Just redefine the console to log over a condition, your condition of course will be a check over which library is accessing the function:
// Your condition, could be anything
let condition = true;
/* Redefine the console object changing only the log function with your new version and keeping all the other functionalities intact
*/
let console = (old => ({
...old,
log: text => { if (condition) old.log(text) }
}))(window.console)
// Redefine the old console
window.console = console;
console.log('hello!')
Hope it helped :)
Yes, you can disable console logs from files based on their path! Here's a solution:
// in ./loud-lib.js
module.exports = {
logsSomething: () => console.log('hello from loud-lib')
}
// in ./silent-lib.js
module.exports = {
logsSomething: () => console.log('hello from silent-lib')
}
// in ./index.js
const loud = require('./loud-lib');
const silent = require('./silent-lib');
// save console.log
const log = console.log;
// redefinition of console.log
console.log = (...params) => {
// define regexp for path of libraries that log too much
const loudLibs = [/loud-lib/];
// check if the paths logged in the stacktract match with at least one regexp
const tooLoud = !!loudLibs.find(reg => reg.test(new Error().stack));
// log only if the log is coming from a library that doesn't logs too much
if (!tooLoud) log(...params);
};
loud.logsSomething();
silent.logsSomething();
$ node ./index.js
hello from silent-lib
This is based on the fact that new Error() produces a stack trace that identifies from which file is the error coming from (recursively).
Based on this observation, you can define an array of regular expression that match the name of libraries you don't want to hear logs from. You can get really specific and creative with the re-definition of console.log, but I kept it simple.
However, be aware of this (especially when using Webpack): if you bundle all your JS assets into one single bundle.js, the stacktrace will always point to bundle.js, thus logging everything. You'll have to go further from my code, for example by using stack-source-map, but I don't have sufficient details on your project to deliver a solution. I hope the ideas above are sufficient for you.

How to disable console.log messages based on criteria from specific javascript source (method, file) or message contents

I am working on project that uses quite a few js libraries and one of them is outputting awful lot into console, it is polluting the airwaves so bad that it makes it hard to debug....
I know how to disable logging completely by overriding console.log with this,
(function (original) {
console.enableLogging = function () {
console.log = original;
};
console.disableLogging = function () {
console.log = function () {};
};
})(console.log);
but how do it do that per source(file/url) of where message originated?
Preamble
The beginning discusses how stuff works in general. If you just care for the code, skip Introduction and scroll to the Solution heading.
Introduction
Problem:
there is a lot of console noise in a web application. A significant amount of that noise is coming from third party code which we do not have access to. Some of the log noise might be coming from our code, as well.
Requirement:
reduce the noise by stopping the log. Some logs should still be kept and the decision about those should be decoupled from the code that is doing the logging. The granularity needed is "per-file". We should be able to choose which files do or do not add log messages. Finally, this will not be used in production code.
Assumption: this will be ran in a developer controlled browser. In that case, I will not focus on backwards compatibility.
Prior work:
First off logging can be enabled/disabled globally using this
(function (original) {
console.enableLogging = function () {
console.log = original;
};
console.disableLogging = function () {
console.log = function () {};
};
})(console.log);
(code posted in the question but also here for reference)
However, that does not allow for any granularity.
This could be modified to work on only specific modules but that cannot be done for third party code.
A mixed approach would be to disable logging globally but enable it in each of our modules. Problem there is that we have to modify each of our files and we will not get some potentially useful external messages.
A logging framework can be used but it might be an overkill. Although, to be honest, that's what I'd go for, I think, but it may need some integration into the product.
So, we need something light-weight-ish that has some configuration and does not need to be pretty.
Proposal:
The Loginator (title subject to change)
Let's start with the basics - we already know we can override the global log function. We'll take that and work with it. But first, let's recognise that the console object supports more than just .log. There could be various logging functions used. So-o-o, let's disable all of them.
Silence everything
//shorthand for further code.
function noop() {}
const savedFunctions = Object.keys(console)
.reduce((memo, key) => {
if(typeof console[key] == "function") {
//keep a copy just in case we need it
memo[key] = console[key];
//de-fang any functions
console[key] = noop;
}
return memo;
},
{});
console.log("Hello?");
console.info("Hello-o-o-o?");
console.warn("Can anybody hear me?");
console.error("I guess there is nobody there...");
savedFunctions.log("MUAHAHAHA!")
This can obviously be improved but it showcases how any and ll logging can be stopped. In reality, console.error should probably be left and console.warn might be also useful. But this is not the be-all-and-end-all solution.
Next, since we can override console functionality...why not supply our own?
Custom logging
const originalLog = console.log;
console.log = function selectiveHearing() {
if (arguments[0].indexOf("die") !== -1) {
arguments[0] = "Have a nice day!";
}
return originalLog.apply(console, arguments)
}
console.log("Hello.");
console.log("My name is Inigo Montoya.");
console.log("You killed my father.");
console.log("Prepare to die.");
That is all the tools we need to roll our own mini-logging framework.
How to do selective logging
The only thing missing is to determine which file something is coming from. We just need a stack trace.
// The magic
console.log(new Error().stack);
/* SAMPLE:
Error
at Object.module.exports.request (/home/vagrant/src/kumascript/lib/kumascript/caching.js:366:17)
at attempt (/home/vagrant/src/kumascript/lib/kumascript/loaders.js:180:24)
at ks_utils.Class.get (/home/vagrant/src/kumascript/lib/kumascript/loaders.js:194:9)
at /home/vagrant/src/kumascript/lib/kumascript/macros.js:282:24
at /home/vagrant/src/kumascript/node_modules/async/lib/async.js:118:13
at Array.forEach (native)
at _each (/home/vagrant/src/kumascript/node_modules/async/lib/async.js:39:24)
at Object.async.each (/home/vagrant/src/kumascript/node_modules/async/lib/async.js:117:9)
at ks_utils.Class.reloadTemplates (/home/vagrant/src/kumascript/lib/kumascript/macros.js:281:19)
at ks_utils.Class.process (/home/vagrant/src/kumascript/lib/kumascript/macros.js:217:15)
*/
(Relevant bit copied here.)
True, there are some better ways to do it but not a lot. It would either require a framework or it's browser specific - error stacks are not officially supported but they work in Chrome, Edge, and Firefox. Also, come on - it's literally one line - we want simple and don't mind dirty, so I'm happy for the tradeoff.
Solution
Putting it all together. Warning: Do NOT use this in production
(function(whitelist = [], functionsToPreserve = ["error"]) {
function noop() {}
//ensure we KNOW that there is a log function here, just in case
const savedFunctions = { log: console.log }
//proceed with nuking the rest of the chattiness away
Object.keys(console)
.reduce((memo, key) => {
if(typeof console[key] == "function" && functionsToPreserve.indexOf(key) != -1 ) {
memo[key] = console[key];
console[key] = noop;
}
return memo;
},
savedFunctions); //<- it's a const so we can't re-assign it. Besides, we don't need to, if we use it as a seed for reduce()
console.log = function customLog() {
//index 0 - the error message
//index 1 - this function
//index 2 - the calling function, i.e., the actual one that did console.log()
const callingFile = new Error().stack.split("\n")[2];
if (whitelist.some(entry => callingFile.includes(entry))) {
savedFunctions.log.apply(console, arguments)
}
}
})(["myFile.js"]) //hey, it's SOMEWHAT configurable
Or a blacklist
(function(blacklist = [], functionsToPreserve = ["error"]) {
function noop() {}
//ensure we KNOW that there is a log function here, just in case
const savedFunctions = {
log: console.log
}
//proceed with nuking the rest of the chattiness away
Object.keys(console)
.reduce((memo, key) => {
if (typeof console[key] == "function" && functionsToPreserve.indexOf(key) != -1) {
memo[key] = console[key];
console[key] = noop;
}
return memo;
},
savedFunctions); //<- it's a const so we can't re-assign it. Besides, we don't need to, if we use it as a seed for reduce()
console.log = function customLog() {
//index 0 - the error message
//index 1 - this function
//index 2 - the calling function, i.e., the actual one that did console.log()
const callingFile = new Error().stack.split("\n")[2];
if (blacklist.some(entry => callingFile.includes(entry))) {
return;
} else {
savedFunctions.log.apply(console, arguments);
}
}
})(["myFile.js"])
So, this is a custom logger. Sure, it's not perfect but it will do the job. And, hey, since the whitelisting is a bit loose, it could be turned to an advantage:
to whitelist a bunch of files that share a substring, say, all myApp can include myApp1.js, myApp2.js, and myApp3.js.
although if you want specific files, you can just pass the full name, including extension. I doubt there would be a bunch of duplicate filenames.
finally, the stack trace will include the name of the calling function, if any, so you can actually just pass that and that will whitelist on per-function basis. However, it relies on the function having a name and it's more likely for function names to clash, so use with care
Other than that, there can certainly be improvements but that is the basis of it. The info/warn methods can also be overriden, for example.
So, this, if used, should only be in dev builds. There are a lot of ways to make it not go into production, so I won't discuss them but here is one thing I can mention: you can also use this anywhere if you save it as a bookmarklet
javascript:!function(){function c(){}var a=arguments.length<=0||void 0===arguments[0]?[]:arguments[0],b=arguments.length<=1||void 0===arguments[1]?["error"]:arguments[1],d={log:console.log};Object.keys(console).reduce(function(a,d){return"function"==typeof console[d]&&b.indexOf(d)!=-1&&(a[d]=console[d],console[d]=c),a},d),console.log=function(){var c=(new Error).stack.split("\n")[2];a.some(function(a){return c.includes(a)})&&d.log.apply(console,arguments)}}(["myFile.js"]);
This is it minified (although I passed it through Babel first, to use ES5 minification) and still configurable, to an extent, as you can change the very end where you can pass the whitelist. But other than that, it will work the same and is completely decoupled from the codebase. It will not run at pageload but if that's needed you can either use this as a userscript (still decoupled) or include it before other JS files in dev/debug builds only.
A note here - this will work in Chrome, Edge and Firefox. It's all the latest browsers, so I assume a developer will use at least one of them. The question is tagged as Chrome but I decided to widen the support. A Chrome only solution could work slightly better but it's not really a big loss of functionality.
I was as troubled as you. This is my approach. https://github.com/jchnxu/guard-with-debug
Simple usage:
localStorage.debug = [
'enable/console/log/in/this/file.ts',
'enable/console/log/in/this/folder/*',
'-disable/console/log/in/this/file.ts',
'-disable/console/log/in/this/folder/*',
// enable all
'*',
].join(',');
The benefit: it's zero-runtime.
Disclaimer: I am the author of this tiny utility
It work in chrome:
...index.html
<html>
<body>
<script>
(function(){
var original = console.log;
console.log = function(){
var script = document.currentScript;
alert(script.src);
if(script.src === 'file:///C:/Users/degr/Desktop/script.js') {
original.apply(console, arguments)
}
}
})();
console.log('this will be hidden');
</script>
<script src="script.js"></script>
</body>
</html>
...script.js
console.log('this will work');
Console.log does not work from index.html, but work from script.js. Both files situated on my desctop.
I've found these settings in the latest (July 2020) Chrome DevTools console to be helpful:
DevTools | Console | (sidebar icon) | user messages
DevTools | Console | (gear icon) | Select context only
DevTools | Console | (gear icon) | Hide network
I like (1) most, I only see the messages from "my" code. (2) hides messages from my iframe.
If it's an option to modify file, you can set a flag at top of file for disabling logs for that:
var DEBUG = false;
DEBUG && console.log("cyberpunk 2077");
To disable logs for all js files, put it once at top of any js file:
var DEBUG = false;
if (!DEBUG) {
console.log = () => {};
}
This is not pretty but will work.
Put something like this in your file before the <script> tag of the "bad" library :
<script>function GetFile(JSFile) {
var MReq = new XMLHttpRequest();
MReq.open('GET', JSFile, false);
MReq.send();
eval(MReq.responseText.replace(/console.log\(/g,"(function(){})("));
}</script>
Then replace the tag
<script src="badLib.js">
With:
GetFile("badLib.js")
Only for short time debugging.

Categories

Resources