Javascript bookmarklet fails on certain sites, cre

2019-03-30 01:39发布

问题:

I noticed that my Javascript bookmarklet was failing on certain sites like Google Reader and Google search results pages (and randomly on some non-Google sites). Looking at the console, I could see that, for these pages, clicking the bookmarklet did not append elements to the head/body like it normally did, but created a new document that looked like this:

<html>
  <head></head>
  <body></body>
</html>

Even when I reduced my bookmarklet to javascript:alert(window.location.href); it would create this blank page and run the bookmarklet therein, so that the alert showed about:blank. On most sites, this blank page is not created and the correct location is shown.

Can someone explain this? Are these sites sandboxing externally run code as a safety measure?

UPDATE: I currently can't reproduce this on browsers other than Chrome 17.0.932.0 dev. Please let me know if anyone else can reproduce these results on Chrome or otherwise.

回答1:

I think this is a bug in Google Chrome, I've filed it to their bug database: https://bugs.webkit.org/show_bug.cgi?id=72606



回答2:

You need to ensure that the topmost code, i.e. the one right after javascript: does not return anything.

Usually this is done by wrapping everything in void():

javascript:void(alert(window.location.href));

It's very odd that it breaks with alert() though since the function itself doesn't return anything...



回答3:

If a javascript: url returns a string it will be used to create a new document:

javascript:'foo bar baz';

This can be a tough issue to debug if you don't know to watch out for it. It can crop up if you use a function that returns a string or end your bookmarklet with a line that sets a string value:

javascript: a = prompt('foo bar baz'); b = a;

A simple solution is to use a closure:

javascript:(function(){ var a; a = prompt('foo bar baz'); window.b = a}());

An alternative is to end with void 0;

javascript: a = prompt('foo bar baz'); b = a; void 0;