0

The problem is that the functions do not seem to be able to see each other.

For Example:

unsafeWindow.helloworld = function() {

    alert('Hello world!');

    helloworld2();//fails with error saying it does not exist
}

unsafeWindow.helloworld2 = function() {

    alert('Hello world!2');

    helloworld();//fails with error saying it does not exist
}

insert("helloworld();"); //appends a script element to the body

Both functions can be called using insert or firebug console but they do not know about each other internally? What is the problem here?

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
Jonathon
  • 2,571
  • 5
  • 28
  • 49

2 Answers2

1

It would help a lot if you format your code:

> unsafeWindow.helloworld = function() {
> 
>     alert('Hello world!');
> 
>     // fails with error saying it does not exist
>     helloworld2(); 
> }
> 
> unsafeWindow.helloworld2 = function() {
> 
>     alert('Hello world!2');
> 
>     //fails with error saying it does not exist
>     helloworld();
> 
> }

You have in infinitely recursive funciton - helloworld calls helloworld2 which calls helloworld and so ad infinitum.

But anyway, you are setting a property of unsafeWindow:

unsafeWindow.helloworld = function() {

but then attempting to call it using an unqualified identifier that is resolved on the scope chain:

[... later, in helloword2 ...]

      helloworld();

So the identifier helloworld is resolved on the scope chain of the execution/variable object created when unsafeWindow.helloworld2 is called.

So helloworld is set as a property of unsafeWindow. When the function is called, the identifier helloworld2 will be resolved using the scope chain of the function.

In browsers, the window/global object is on the scope chain so variable names may be found there (i.e. variables may resolve to properties of the global object if not found sooner in the scope chain), but I suspect that when unsafeWindow.helloworld is called, that its scope chain ends with the document's global object, not unsafeWindow. Otherwise calls to functions in the document would also have unsafeWindow on their scope chain, which doesn't seem right to me.

Or I might be completely wrong about that. :-)

RobG
  • 142,382
  • 31
  • 172
  • 209
  • Well that is a tongue twister, but it helped solve my problem none the less. For anyone who did not understand that, here is my interpretation(which I am sure is seriously flawed in some way): Functions are "compiled" when they are created so even tho the function will be embedded into the web page you still need to call it using the unsafeWindow scope while creating it (so that GM can find it). ` unsafeWindow.helloworld2 = function(){ alert("HW"); unsafewindow.helloworld(); }` OK and I still cannot figure out this formatting, will look into it before I post again. – Jonathon May 19 '11 at 13:24
  • OK and I still cannot figure out this formatting, will look into it more before I post again. Is help simply wrong, I am not sure why the `` did not work and why any website would use this confusing a system for formatting. – Jonathon May 19 '11 at 13:30
1

There are multiple problems.

  1. Since the functions are being defined in the unsafeWindow scope, they must be called that way, in the Greasemonkey script.
    Like so:

    unsafeWindow.helloworld = function () {
    
        alert ('Hello world!');
        unsafeWindow.helloworld2 ();
    }
    
    unsafeWindow.helloworld2 = function () {
    
        alert ('Hello world!2');
        unsafeWindow.helloworld ();
    }
    


  2. Where is insert() coming from?! To call these functions you would use:

    // WARNING this will launch an infinite loop!!
    unsafeWindow.helloworld2 ();
    


  3. Don't do this! The only reason to define a function that way is to override/overwrite a function that was already on the target page. In the rare cases when you DO want to override a website's JavaScript, the best method depends on the details.

    You can use lot's of unsafeWindow escaping (as shown), or rewrite functions en masse, but the best approach is often just to delete the page's function:
    (unsafeWindow.badFunc = function () {})
    and replace/add the changed features in the GM script scope.


  4. But for the question as it's currently posted, you don't need to do any of that. Based on what's shown, the script would just be:

    helloworld = function () {
    
        alert ('Hello world!');
        helloworld2 ();
    }
    
    helloworld2 = function () {
    
        alert ('Hello world!2');
        helloworld ();
    }
    
    // WARNING this will launch an infinite loop!!
    helloworld2 ();
    
Community
  • 1
  • 1
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • Well maybe I misunderstand the use of unsafe window. I am simply trying to add JavaScript to an existing webpage and then have it be executable post GM. so for example: in GM: unsafeWindow.newfunction = function(){...} in web page: you say I have to use unsafeWindow.newfunction? but I did not think that that was available after GM finished running. – Jonathon May 19 '11 at 13:01
  • insert() like I said simply creates a script element and appends it to the webpage's body (ie it is just a way to call the code from within the webpage) (I tried using this to insert the functions I am now trying to insert using unsafeWindow but I think I had the same scope problem). – Jonathon May 19 '11 at 13:18
  • OK, adding the unsafeWindow to my code seems to have fixed it. thanks so much for the help. – Jonathon May 19 '11 at 13:19