0

With the following (GreaseMonkey) user script I am trying to find (and later access) a JavaScript object (namely 'Blazor'):

// ==UserScript==
// @name         Test
// @version      1
// @grant        none
// @run-at       document-end
// ==/UserScript==

window.addEventListener ("load", doStuff);

function doStuff() { 
    setTimeout(function() {
        console.log("window.hasProperty('Blazor'): " + window.hasOwnProperty("Blazor"));
        console.log("'Blazor' in window:           " + ('Blazor' in window));
        console.log(window);
    }, 2000);    
}

When I run the script (i.e., reload the page), I get the following output in Firefox' console:

Screenshot of the Firefox JavaScript console

So window.Blazor can not be found. However, when I inspect (click on) the window object I can see the Blazor property:

Screenshot of the Firefox JavaScript console

Calling 'Blazor' in window in the console also returns true.

Why is this property of window not (yet?) available and how can I find and access it?

Update:

Based on madalinivascu's answer I tried the following:

function doStuff() {
  console.log("<doStuff>");
  
  var promise = new Promise(function(resolve, reject) {
    var interval = setInterval(function() {
      console.log("checking for Blazor");
      if ('Blazor' in window) {
        console.log("Blazor found");
        clearInterval(interval);
        resolve(window.Blazor);
      }
    }, 1000);
  });
  
  promise.then(successCallback, failureCallback);
  
  console.log("</doStuff>");
}

function failureCallback(error) {
  console.log("failure: " + error);
}

function successCallback(result) {
  console.log("success: " + result);
}

which results in the following output:

Screenshot of the Firefox console

So the function checking for Blazor is called indefinitely without success in finding it.

Robert
  • 872
  • 3
  • 10
  • 15
  • the `Blazor` variabile is intitalized **after** the windows load event, you need to listen to an event generated by the `Blazor` object initiating(if it has any), another solution will be a timeout function to wait for `Blazor `to initiate, this does not guarantee that `Blazor` will initiate in that time frame – madalinivascu Jun 17 '21 at 06:36
  • Thank you. Since I don't know any events I could listen to, I have tried [this approach](https://stackoverflow.com/questions/31750518/javascript-waiting-until-property-of-an-element-is-ready-to-continue) which is the timeout function you described. Unfortunately, it does not work: Although `console.log(window)` already showed my the window including the `Blazor` property, the timeout function that regularly checked for it (in the meantime) did not find it. – Robert Jun 17 '21 at 07:14
  • Is it possible the "window" you get in Greasemonkey is not the same "window" that has the Blazor property? – Mister Magoo Jun 17 '21 at 09:59
  • @MisterMagoo Thank you, that lead to the right path! Apparently, the script runs in another environment. Using [script injection](https://stackoverflow.com/questions/13485122/accessing-variables-from-greasemonkey-to-page-vice-versa/13485650#13485650) I was able to access the 'real' window object (and thus Blazor). – Robert Jun 17 '21 at 10:17
  • I'd suggest you add your own answer and close it. – Mister Magoo Jun 17 '21 at 10:43

2 Answers2

1

The solution is to use script injection, since the GreaseMonkey script runs in another context and thus gets another window object.

More precisely, attaching the function doStuff with addJS_Node defined in that answer (addJS_Node (null, null, doStuff);) instead of using window.addEventListener ("load", doStuff); works.

Robert
  • 872
  • 3
  • 10
  • 15
0

You can test for the variable using a setInterval and a promise

function doStuff() { 
    var promise = new Promise(function(resolve, reject) {
    var interval = setInterval(function() {
          if(window.Blazor || window.hasOwnProperty('Blazor')) {
              clearInterval(interval);
              resolve(window.Blazor);//rezolve promise with the balzor variable
          }
        }, 200);//check every 200ms for the blazor variable
    })
    promise.then(function(blazor) {
        console.log(blazor);//do other stuf with the blazor variable
    })    
}
madalinivascu
  • 32,064
  • 4
  • 39
  • 55
  • Thank you. There are closing brackets (`})`) missing. Could you please clarify, where they should go? I suppose before `promise.then...` though then I had no success with that approach, yet. (The check `if ('Blazor in window)` at some points stops but the promise is never called.) – Robert Jun 17 '21 at 07:53
  • sory, they should go before `promise.then`, updated my answer – madalinivascu Jun 17 '21 at 07:56
  • Thanks. Unfortunately, that doesn't work either. I have updated my question accordingly to explain what I did and what the outcome is. – Robert Jun 17 '21 at 08:35
  • better check if window.Blazor is defined or window has propery Blazor `window.hasOwnProperty('Blazor ')`, see updated answer – madalinivascu Jun 17 '21 at 08:56