Окрім переосмислення 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]
ви очікуєте наступного результату:
Після маніпулювання за InjectedScript._evaluateAndWrap
оцінкою того самого виразу, дає такий вихід:
Як ви бачите ліворуч стрілку, що вказує на вихід, все ще є, але на цей раз ми отримуємо об'єкт. Де результат виразу, масив[1,2,3,4]
представлений у вигляді об'єкта з усіма описаними властивостями.
Я рекомендую спробувати оцінити цей і той вираз, включаючи ті, що генерують помилки. Це досить цікаво.
Додатково подивіться на об’єкт is
- InjectedScriptHost
- . Він пропонує деякі методи, з якими можна пограти та трохи ознайомитись із внутрішністю інспектора.
Звичайно, ви можете перехопити всю цю інформацію і все-таки повернути початковий результат користувачеві.
Просто замініть оператор return у шляху 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
функції.