chrome.tabs.executeScript(): How to get result of content script? - javascript

According to the documentation for chrome.tabs.executeScript (MDN), the callback function accepts an "array of any result" result set from the execution of the script(s). How exactly do you use this to get results? All of my attempts end up with undefined being passed to the callback.
I have tried returning a value at the end of my content script, which threw a Uncaught SyntaxError: Illegal return statement. I tried using the optional code object argument {code: "return "Hello";} with no success.
I feel like I am not understanding what is meant by "The result of the script in every injected frame", in the documentation.

chrome.tabs.executeScript() returns an Array with "the result of the script" from each tab/frame in which the script is run.
"The result of the script" is the value of the last evaluated statement, which can be the value returned by a function (i.e. an IIFE, using a return statement). Generally, this will be the same thing that the console would display as the results of the execution (not console.log(), but the results) if you executed the code/script from the Web Console (F12) (e.g. for the script var foo='my result';foo;, the results array will contain the string "my result" as an element). If your code is short, you can try executing it from the console.
Here is some example code taken from another answer of mine:
chrome.browserAction.onClicked.addListener(function(tab) {
console.log('Injecting content script(s)');
//On Firefox document.body.textContent is probably more appropriate
chrome.tabs.executeScript(tab.id,{
code: 'document.body.innerText;'
//If you had something somewhat more complex you can use an IIFE:
//code: '(function (){return document.body.innerText;})();'
//If your code was complex, you should store it in a
// separate .js file, which you inject with the file: property.
},receiveText);
});
//tabs.executeScript() returns the results of the executed script
// in an array of results, one entry per frame in which the script
// was injected.
function receiveText(resultsArray){
console.log(resultsArray[0]);
}
This will inject a content script to get the .innerText of the <body> when the browser action button is clicked. you will need the activeTab permission.
As an example of what these produce, you can open up the web page console (F12) and type in document.body.innerText; or (function (){return document.body.innerText;})(); to see what will be returned.

Related

Return text from URL in GTM Custom JS variable

I need to capture text from the file saved under URL (ex. https://fiddle.jshell.net/robots.txt) And return it under the function.
What is on my mind:
function(){
var url = 'https://fiddle.jshell.net/robots.txt'
var storedText;
fetch(url)
.then(function(response) {
response.text().then(function(text) {
storedText = text;
done();
});
});
function done() {
return storedText;
}
});
Unfortunately this function is not working. I received an error: Error at line 2, character 2: Parse error. primary expression expected Type: JavaScript compiler error
This should be used as a Custom JavasSript Variable in Google Tag Manager
Also this How do I return the response from an asynchronous call? is not explaining my issue and all solutions were checked by me, nothing worked due Parse error or console error.
I have to use GTM custom JavaScrip Variable, I can use anything else.
Simpler JS than better.
Function done() returns storedText value to a point of call, i. e. it works but returns nothing.
I would not recommend using an external call within a custom Custom JavasSript Variable in GTM:
You can not really control how often a Custom JavasSript Variable is executed in GTM. An it is executed a lot.
Just do the test and run a console log from a custom javascript variable.

Script not printing error in JavaScript Chrome console

I have just spent far too long trying to find a problem with the code below.
In turned out that because of the context that addRoute was called in, keys() was not returning the keys of the results object. To fix this I had to use Object.keys() despite it working without a problem in the JavaScript console (which I later realised was because of the context).
My question is, why didn't this show in my JavaScript console? It took me quite a while to realise (I have cropped the full code, the actual function is a lot bigger).
Wrong, but no error in the console:
Map.prototype.addRoute = function (results) {
var sectionsIDs = keys(results);
}
Correct
Map.prototype.addRoute = function (results) {
var sectionsIDs = Object.keys(results);
}
Your first function uses the keys console API function.
That "Command Line API Reference" page includes the warning:
Note: This API is only available from within the console itself. You cannot access the Command Line API from scripts on the page.
Thus, it is by design that the keys function only exists for code run directly on the console.
Chrome gives you a small hint about the keys function being a console-only function if you view it in the console:
> keys
function keys(object) { [Command Line API] }

Different behavior seen accessing value in stored variable vs function call that returns the variable

Apologies for what must be a total newbie question. I'm starting to play with Backbone talking to an existing Rails app. I'm using the Console in Chrome to test out some JS functions, and I'm seeing behavior that I cannot understand.
I've defined a JS function called apiGet which just wraps a jQuery AJAX call with some custom stuff jammed into the HTTP request header.
When I call apiGet and store the result in a variable, I can then call .responseText on that variable and see the contents of that field.
However, if I just try to call .responseText on the apiGet(...) call, i.e. apiGet(...).responseText the result displayed is undefined. This makes no sense to me :-)
I'm missing something obvious -- can someone clue me in?
Here's what the console looks like:
> var url = 'http://localhost:3002/api/exercises/11';
undefined
> result = apiGet(url);
Object {readyState: 1, getResponseHeader: function, getAllResponseHeaders: function, setRequestHeader: function, overrideMimeType: function…}
> result.responseText
"{"id":1,"number":2,"version":1,"markup":null,"html":null,"background":null}"
> apiGet(url).responseText
undefined
It looks like your function apiGet returns an xhr (request object). This will execute asynchronously, so that responseText isn't available until the response comes back from the server. When you call the property directly on the return, it happens so fast that the server hasn't responded yet, but when you use the console manually, by the time you type out result.responseText and press enter, the result is already in.
Just a guess of course, since I haven't seen the contents of getApi.

How to patch console.error or info but leave jump urls intact for Firebug?

I saw many posts how to replace the JS console functions by others but no one leaves it intact for Firebug.
When I replace any of them, it calls my custom function but it reports the message from the very same place the new function comes from.
The goal here is to receive any of those console messages and display them somewhere else whilst I still can jump to the callee in the Firebug console.
Is this possible at all ?
Update :
for instance (PSEUDO) :
//keep the old one
var oriFn=console.error;
console.error=function(){
someOtherFunc(arguments);//send to server for instance
oriFn(arguments);
}
Now somewhere else I'd like to call as usual console.error('bla'); In the Firebug console, it prints my message but shows a link to the replacement code above. I want in the Firebug console the link to the callee's parent function and that's it.
Use a function pointer. Given foo.js:
function foo()
{
console.error = console.log; //Reassign console.error
location.hash = document.title; //Do something
console.error("Not the mama"); //Outputs line foo.js:5
}
References
How to de-anonymize your anonymous functions
JavaScript Wikibook: Anonymous Functions
JavaScript Anonymous Functions
Javascript function declarations vs function operators

Can I throw an exception in Javascript, that stops Javascript execution?

I try to simulate a problem where a script that is loaded from an external url stops execution of any more scripts on my site.
I tried to simulate such a problem by calling a function that does not exits. I can see the error in firebug but different scripts on the page are still executed.
Are there different kinds of errors in Javascripts? If yes: what kind of error stops script execution? I only need this answer for Firefox.
EDIT
This question is easy to misunderstood but Rob W got it: I need to throw an exception and that exception needs to stop further script execution.
Answer to the title: No
Answer to "Are there different kinds of errors in JavaScript**: Yes, see MDN: Error
Syntax errors will prevent a whole script block from being executed,
other errors (TypeErrors, Reference errors) will only stop the execution after the occurrence of the error.
Different <script> blocks are executed separately. You cannot prevent the second block from execution by throwing an error in the first block (Demo: http://jsfiddle.net/WJCEN/).
<script>Example: Syntax error in this script.</script>
<script>console.log('Still executed.')</script>
Also, if an error is caught using try-catch (demo: http://jsfiddle.net/WJCEN/1/), then the error will not even stop the execution a whole block.
try {throw 'Code';}catch(e){}
console.log('Still executed');
There is no general one-fit-all method to stop all code from running. For individual scripts, you can use some tricks to prevent the code from running further.
Example 1 (demo): Temporary overwrite a method
1: <script>window._alert = alert;alert=null;</script>
2: <script>alert('Some code!');confirm('Not executing');</script>
3: <script>alert=_alert;delete window._alert;alert('Done!');</script>
This method is based on the fact that script 2 expects alert to be a function. We have rewritten alert to a non-function property (script 1). Script 2 throws a TypeError, and the second block is skipped.
We restore the original values in script 3.
Example 2 (demo): Define a constant method, which cannot be overwritten.
4. <script>Object.defineProperty(window, 'test',{value:null});</script>
5. <script>var test=function(){alert('Test');};test();alert('What?');</script>
This methods relies on the Object.defineProperty method, to effectively define a constant value. In strict mode, the var test declaration would throw a TypeError: "test is read-only".
When strict mode is not enables, a TypeError will be thrown at test(): "test is not a function" (because we defined test to be constant, in script 4).
Note: The last method is not working correctly with function declarations (see bug #115452, Chrome 17)
Use
try catch finally block
It will do the trick
you can use the error object which support the following two properties:
name: The name of the error.
message: A description of the error.
for example to stop execution you can use : throw new Error("myError");
Are there different kinds of errors in Javascripts?
Besides the generic Error constructor, there are six other core errors in JavaScript:
see here details on these errors.
Stop the execution with
throw new Error('stopIt');
This will also do the trick:
throw 'Stop It!';

Categories

Resources