Oltre a ridefinire console._commandLineAPI
, ci sono altri modi per entrare in InjectedScriptHost nei browser WebKit, per prevenire o alterare la valutazione delle espressioni inserite nella console dello sviluppatore.
Modificare:
Chrome ha risolto questo problema in una versione precedente. - che deve essere stato prima di febbraio 2015, come ho creato l'essenza in quel momento
Quindi ecco un'altra possibilità. Questa volta ci colleghiamo, un livello sopra, direttamente InjectedScript
piuttosto che InjectedScriptHost
in contrasto con la versione precedente.
Il che è carino, dato che puoi direttamente applicare la patch alle scimmie InjectedScript._evaluateAndWrap
invece di dover fare affidamento InjectedScriptHost.evaluate
perché ciò ti dà un controllo più preciso su ciò che dovrebbe accadere.
Un'altra cosa piuttosto interessante è che possiamo intercettare il risultato interno quando viene valutata un'espressione e restituirla all'utente invece del normale comportamento.
Ecco il codice, che fa esattamente questo, restituisce il risultato interno quando un utente valuta qualcosa nella console.
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);
È un po 'prolisso, ma ho pensato di aggiungere alcuni commenti
Quindi normalmente, se un utente, ad esempio, valuta, [1,2,3,4]
ti aspetteresti il seguente output:
Dopo il monkeypatch che InjectedScript._evaluateAndWrap
valuta la stessa espressione, fornisce il seguente output:
Come vedi la piccola freccia sinistra, che indica l'output, è ancora lì, ma questa volta otteniamo un oggetto. Dove il risultato dell'espressione, l'array [1,2,3,4]
è rappresentato come un oggetto con tutte le sue proprietà descritte.
Consiglio di provare a valutare questa e quell'espressione, comprese quelle che generano errori. È abbastanza interessante
Inoltre, dai un'occhiata all'oggetto is
- InjectedScriptHost
- . Fornisce alcuni metodi con cui giocare e ottenere un po 'di conoscenza degli interni dell'ispettore.
Naturalmente, potresti intercettare tutte quelle informazioni e comunque restituire all'utente il risultato originale.
Basta sostituire la dichiarazione di ritorno nel percorso else con un console.log (res)
seguente a return res
. Quindi finiresti con il seguente.
Fine modifica
Questa è la versione precedente che è stata riparata da Google. Quindi non è più possibile.
Uno di questi è agganciarsi Function.prototype.call
Chrome valuta l'espressione immessa inserendo call
la sua funzione di valutazione con InjectedScriptHost
asthisArg
var result = evalFunction.call(object, expression);
Detto questo, è possibile ascoltare per la thisArg
di call
essere evaluate
e di ottenere un riferimento al primo argomento ( 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);
}
};
}
Ad esempio, è possibile che venga visualizzato un errore relativo al rifiuto della valutazione.
Ecco un esempio in cui l'espressione immessa viene passata a un compilatore CoffeeScript prima di passarla alla evaluate
funzione.