2

I have a bookmark that's a JavaScript bookmark. For example:

javascript:alert('hi');

I'd like to be able to get the source of the currently running JavaScript bookmark, from within the bookmark itself, so in pseudocode:

javascript:alert(currentlyExecutingScript.text);

Which would alert

javascript:alert(currentlyExecutingScript.text);

How can I do this? I prefer cross browser solutions, but am completely fine with just Chrome specific solutions!

Why am I interested in this? Because I'm writing a bookmarklet that refers to itself.

Toothbrush
  • 2,080
  • 24
  • 33
Brad Parks
  • 66,836
  • 64
  • 257
  • 336

3 Answers3

4

As location refers to the current page's URL, and JavaScript bookmarks do not change location, this is not possible in any current browsers.

However, it is possible to do what you want in JavaScript:

javascript:void function f(){alert(f.toString())}()

That will alert the following:

function f(){alert(f.toString())}

The toString() method, when called on a function, returns a string representing the source code of the function (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/toString).

Credit

@SergeSeredenko suggested to use void.

When using an immediately-invoked function expression, void can be used to force the function keyword to be treated as an expression instead of a declaration.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void#Immediately_Invoked_Function_Expressions

Toothbrush
  • 2,080
  • 24
  • 33
  • 1
    I'd anonymize it to not mess with window: `void function f(){alert(f+'')}()` – Serge Seredenko Oct 03 '15 at 16:17
  • @SergeSeredenko I edited my answer earlier, and credited you. However, it's not actually necessary to use `void`. A function declaration does not change the global scope ([source](https://en.wikipedia.org/wiki/Bookmarklet)). – Toothbrush Oct 03 '15 at 16:52
  • What do you mean? You can use `(function f()})()` or `void`. Without both, like `function f(){};f()`, f will go global. Test it if you wish. – Serge Seredenko Oct 03 '15 at 17:08
  • Doesn't matter. Test it and you'll see. Bookmarklet affects global scope. – Serge Seredenko Oct 03 '15 at 22:48
  • @SergeSeredenko Yeah, you're right. I don't know what happened; I must have got two tabs confused when I tested it yesterday. – Toothbrush Oct 05 '15 at 09:48
0

You could write your script in a string, and an evil eval to execute it, with the script having a reference to itself :

javascript:var script = "alert('hi'); alert(script)";
eval(script);

It'll alert "hi", and then the content of script.

Maen
  • 10,603
  • 3
  • 45
  • 71
0

The simplest, though definetely not the safest, way of achieving this is by storing your code in a string, and evaluating that string when you click the bookmark.

var code = "alert('Hi');var num = 988;alert(num + 12)";
//code contains the code you wish to run
eval(code);
//runs the code.
alert(code); 
//alerts the code.

I would be very careful with the use of the eval() function.

See this SO question for more information.

Community
  • 1
  • 1
Deep
  • 920
  • 8
  • 22
  • Why do you say *definetely not the safest*? I don't see any risk related to `eval` here. – Maen Oct 03 '15 at 16:15
  • Depending on implementation, someone could modify the `code` variable too run what ever malicious code they want. – Deep Oct 03 '15 at 16:22