Помимо переопределения console._commandLineAPI
, есть несколько других способов проникнуть в InjectedScriptHost в браузерах WebKit, чтобы предотвратить или изменить оценку выражений, введенных в консоль разработчика.
Редактировать:
Chrome исправил это в прошлом выпуске. - что должно было быть до февраля 2015 года, когда я создал суть в то время
Так что вот еще одна возможность. На этот раз мы подключаемся, на уровень выше, напрямую, InjectedScript
а не InjectedScriptHost
в отличие от предыдущей версии.
Это довольно приятно, так как вы можете напрямую использовать патч для обезьяны InjectedScript._evaluateAndWrap
вместо того, чтобы полагаться на него, InjectedScriptHost.evaluate
поскольку это дает вам более детальный контроль над тем, что должно произойти.
Еще одна довольно интересная вещь заключается в том, что мы можем перехватить внутренний результат при вычислении выражения и вернуть его пользователю вместо нормального поведения.
Вот код, который делает именно это, возвращает внутренний результат, когда пользователь что-то оценивает в консоли.
var is;
Object.defineProperty(Object.prototype,"_lastResult",{
get:function(){
return this._lR;
},
set:function(v){
if (typeof this._commandLineAPIImpl=="object") is=this;
this._lR=v;
}
});
setTimeout(function(){
var ev=is._evaluateAndWrap;
is._evaluateAndWrap=function(){
var res=ev.apply(is,arguments);
console.log();
if (arguments[2]==="completion") {
//This is the path you end up when a user types in the console and autocompletion get's evaluated
//Chrome expects a wrapped result to be returned from evaluateAndWrap.
//You can use `ev` to generate an object yourself.
//In case of the autocompletion chrome exptects an wrapped object with the properties that can be autocompleted. e.g.;
//{iGetAutoCompleted: true}
//You would then go and return that object wrapped, like
//return ev.call (is, '', '({test:true})', 'completion', true, false, true);
//Would make `test` pop up for every autocompletion.
//Note that syntax as well as every Object.prototype property get's added to that list later,
//so you won't be able to exclude things like `while` from the autocompletion list,
//unless you wou'd find a way to rewrite the getCompletions function.
//
return res; //Return the autocompletion result. If you want to break that, return nothing or an empty object
} else {
//This is the path where you end up when a user actually presses enter to evaluate an expression.
//In order to return anything as normal evaluation output, you have to return a wrapped object.
//In this case, we want to return the generated remote object.
//Since this is already a wrapped object it would be converted if we directly return it. Hence,
//`return result` would actually replicate the very normal behaviour as the result is converted.
//to output what's actually in the remote object, we have to stringify it and `evaluateAndWrap` that object again.`
//This is quite interesting;
return ev.call (is, null, '(' + JSON.stringify (res) + ')', "console", true, false, true)
}
};
},0);
Это немного многословно, но я подумала, что добавлю некоторые комментарии
Поэтому обычно, если пользователь, например, оценивает, [1,2,3,4]
вы ожидаете следующий результат:
После того, как monkeypatching InjectedScript._evaluateAndWrap
оценивает то же самое выражение, выдает следующий вывод:
Как вы видите, маленькая левая стрелка, обозначающая вывод, все еще там, но на этот раз мы получаем объект. Где результат выражения, массив [1,2,3,4]
представлен как объект со всеми описанными его свойствами.
Я рекомендую попытаться оценить это и то выражение, в том числе те, которые вызывают ошибки. Это довольно интересно.
Кроме того, взгляните на is
- InjectedScriptHost
- объект. Он предоставляет некоторые методы, с которыми можно поиграть и получить представление о внутренностях инспектора.
Конечно, вы можете перехватить всю эту информацию и все равно вернуть исходный результат пользователю.
Просто замените оператор возврата в пути else console.log (res)
следующим a return res
. Тогда вы получите следующее.
Конец Правки
Это предыдущая версия, которая была исправлена Google. Следовательно, это больше невозможно.
Один из них подключается к Function.prototype.call
Chrome оценивает введенное выражение, используя call
его функцию eval InjectedScriptHost
какthisArg
var result = evalFunction.call(object, expression);
Учитывая это, вы можете слушать к thisArg
из call
существ evaluate
и получить ссылку на первый аргумент ( InjectedScriptHost
)
if (window.URL) {
var ish, _call = Function.prototype.call;
Function.prototype.call = function () { //Could be wrapped in a setter for _commandLineAPI, to redefine only when the user started typing.
if (arguments.length > 0 && this.name === "evaluate" && arguments [0].constructor.name === "InjectedScriptHost") { //If thisArg is the evaluate function and the arg0 is the ISH
ish = arguments[0];
ish.evaluate = function (e) { //Redefine the evaluation behaviour
throw new Error ('Rejected evaluation of: \n\'' + e.split ('\n').slice(1,-1).join ("\n") + '\'');
};
Function.prototype.call = _call; //Reset the Function.prototype.call
return _call.apply(this, arguments);
}
};
}
Например, вы можете выдать ошибку, что оценка была отклонена.
Вот пример, где введенное выражение передается компилятору CoffeeScript перед передачей его evaluate
функции.