1

Now, I'm working with userscript for a browser game. And I have some problems with sandbox and initialization.
As a solution, I found a way with creating a new element (script) and inserting the object in element.

var script = document.createElement("script");
script.type = "text/javascript";
script.innerHTML = "var Class = { ... }";
document.body.appendChild(script);

But I have a very large object and convert it to a string rather problematic and time consuming.
I have an object that looks like this:

{
addToStorage : Function,
getFromStorage : Function,
getID : Function
settings : Object,
langs : Object,
init : Function,
version : Number,
author: String
}

Any ideas, how to convert it to string or insert into global window?

Sorry for my bad English.

  • Thanks for all. I have found the solution for problem. I use this: `(function (fn) { var script = document.createElement('script'); script.setAttribute("type", "application/javascript"); script.textContent = '(' + fn + ')();'; document.body.appendChild(script); // run the script document.body.removeChild(script); // clean up })(function() { // here is any code })` – Nikita Shelimov Feb 08 '15 at 21:38

2 Answers2

1

Use the unsafeWindow object to break out of the greasemonkey sandbox.

To break out of Chrome's isolated environment, according to Are Chrome user-scripts separated from the global namespace like Greasemonkey scripts? you need to insert a <script> element into the DOM.

You shouldn't store that script's source in an escaped string, better take a JS object and stringify it. For plain ones, you can use JSON, for more complex things put everything into a function and call .toString() on that:

function moduleClosure(global) {
    // do something
    return some object
}
var script = document.createElement("script");
script.type = "text/javascript";
script.innerText = "var Class = "+moduleClosure+"(window);";
document.body.appendChild(script);
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 1
    @PointedEars, why the downvote? Injecting function code is close to standard practice for Chrome userscripts. – Brock Adams Oct 01 '12 at 03:45
1

In Firefox, you can use the .toSource() function on objects. So the answer is ditch Chrome and switch to Firefox. (^_^)

But assuming you don't want to do that, the answer gets messy, as even JSON.stringify() won't work if the object as function properties, like yours does.

So, you can inject your object source using a multiline string (see the link for a variety of techniques).

Or you can make or use a an object stringifier like objToString, below. Warning, objToString is just a quick and dirty first attempt, you might be smarter to grab something like JavaScript var_export, instead.

var myObjX =  {
    someFunction:   function () {console.log ("foo");},
    settings:       {init: 2},
    langs:          {a: "En", b: "Jp"},
    version:        99,
    author:         "Anon"
}

function objToString (obj) {
    var str = '{ ';
    for (var p in obj) {
        if (obj.hasOwnProperty (p) ) {
            str += p + ': ';
            switch (typeof obj[p]) {
                case "object":
                    str += objToString (obj[p]);
                    break;
                case "string":
                    str += '"' + obj[p] + '"';
                    break;
                default:
                    str += obj[p];
                    break;
            }
            str += ',\n';
        }
    }
    return str.slice (0, str.length-2) + ' }';
}

var script          = document.createElement("script");
script.type         = "text/javascript";
script.textContent  = "var injectedX = " + objToString (myObjX);
document.body.appendChild (script);
Community
  • 1
  • 1
Brock Adams
  • 90,639
  • 22
  • 233
  • 295