1

In this weird situation, I need to convert a JS function into a string, and then then that string into a dynamically generated <script> tag (which uses type javascript/worker so as to not be executed).

I'm working on a user script, injecting code to create a shared web worker between two third party sites. The thing about user scripts is you usually just want to use one file for the script's functionality, and web workers like to use a separate JS file for the worker. Well there's a way around that using a Blob. However, remember I'm only working with a script file, not an HTML file for the user script, so I want to store this part (the shared worker code) as a function in my script:

var worker = function() {
  self.addEventListener('connect', function(e) {
    var port = e.ports[0];
    port.addEventListener('message', function(e) {
      var message = e.data;
      port.postMessage(message);
    });
    port.start();
  });
};

then use the toString() on it so I can inject it into a dynamically generated script tag in the third party pages, so it ends up like this without the script calling on any extra files:

<script id="worker1" type="javascript/worker">
    self.addEventListener('connect', function(e) {
        var port = e.ports[0];
        port.addEventListener('message', function(e) {
            var message = e.data;
            port.postMessage(message);
        });
        port.start();
    });
</script>

However using the toString() method results in the word function being included, as shown in this example:

Remember I was going to append the function to a script tag with type javascript/worker instead of text/javascript so the function wouldn't be executed until it was converted to a blob and used as a file source for the worker, but here I'm going to use text/javascript so you can see the error when it executes.

var worker = function() {
  self.addEventListener('connect', function(e) {
    var port = e.ports[0];
    port.addEventListener('message', function(e) {
      var message = e.data;
      port.postMessage(message);
    });
    port.start();
  });
};

var func = worker.toString();
var script = document.createElement("script");
script.type = "text/javascript";
script.id = "worker1";
$("head").append(script);

$('body').append(script);
$('#worker1').append(func);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

enter image description here


Just so you can understand what I'm doing, because it might be confusing, a function like this would then convert the above non-executed script tag into a Blob and use that instead of an external file to create the shared worker:

var blob = new Blob([document.querySelector('#worker1').textContent], 
{ type: "text/javascript" });
var sharedWorker = new SharedWorker(window.URL.createObjectURL(blob));

So, how can I inject the contents of the function into a script tag without including the function wrapper syntax(function (){)?

Community
  • 1
  • 1

1 Answers1

0

You can use string's methods to do this:

I think this can help you or something like this, to remove the function name.

function test(){
      console.log('TEST TEST');
}

    var fBody = test.toString()
    var index = fBody.indexOf('{');
    var functionBodyAsArray = fBody.substring(index + 1);
    functionBodyAsArray = functionBodyAsArray.substring(0, functionBodyAsArray.length - 1);

    console.log(functionBodyAsArray );
Suren Srapyan
  • 57,890
  • 10
  • 97
  • 101
  • Interesting approach, there's an error with your code though, because the opening and closing brackets are still there. And a `)` is missing from `console.log`. I suspected this kind of string manipulation or Regex would be difficult to do without risking some weird bugs messing up the inner code. –  Aug 02 '16 at 05:00
  • A shorter way i figured out was just use `var functionBodyAsArray = fBody.substring(index + 3, fBody.length - 1);` –  Aug 02 '16 at 05:16
  • But a small problem is if you were to add a space between the `()` and the `{`, the bracket isn't removed. This can be avoided, but some JS cleaning functions might add a space there. –  Aug 02 '16 at 05:20
  • 1
    @Viziionary if you will find the index of '}' how many spaces want to add it will not bring to a problem. – Suren Srapyan Aug 02 '16 at 05:24