4

Specific example: the haystack.js script from How Big is Your Haystack?

I've searched for an answer and everything seems to point to using the //# sourceURL=name.js comment. However, the mechanics of how to accomplish this elude me (maybe I'm just dense).

Everyone always points to Debugging JavaScript, but the demo is broken (same-origin error). Other common examples do not provide insight for working with an external script such as this.

I've tried using Live Edit to insert the sourceURL comment, but so far the eval script never shows up in the Sources tab.

Would someone please walk me through the steps to complete this task?

UPDATE: This has proved to be an interesting and annoying endeavour. This particular site makes the task needlessly difficult with the following complications:

  • The haystack.js script includes document.write() statements (which load the other scripts used). These must be removed before the script is reloaded, otherwise the DOM is cleared.

  • The author uses a queer, backtick cipher form of obfuscation on the code. Therefore, code modifications (including the sourceURL) have to be made after obfuscation is removed, but before the eval takes place.

I kludged a partial solution. After loading jQuery into the page, I run this script:

$.ajax({
  url: '/js/haystack.js',
  dataType: 'text'
}).done(function(data) {
    // Remove document.write() statements and append sourceURL comment after obfuscation is removed
    var refactored = data.replace(/return d/, "return d.replace(/document\.write[^;]+;/g, '') + '\\n//# sourceURL=haystack.js\\n';");
    $('head').append('<script type="text/javascript">' + refactored + '</script>');
});

DevTools Source Tag after script

Now haystack.js appears in the (no domain) tree of the Sources tab. Breakpoints can be set, but there is odd behavior. Seems the DOM event handlers are still bound to the original script (breakpoints in reloaded script handlers are never reached). Executing pageInit() again rebinds the handlers to the modified script, but page updates are still erratic. Not sure why the behavior persists. I can step through the code and everything appears normal there, but page updates seem to lag behind the code. The fact that the code violates almost every javascript best practice is no doubt a factor.

2

1 Answer 1

6

This question really intrigued me. I hope my answer helps. I started with Set breakpoints and debug eval'd JavaScript and then expanded it a bit

Here is the plunker

Better than using eval, you can insert a script element into a document.

var js = "console.log('this is line 1');"
addCode(js); // Right now! Debuggable!

// Dynamically evaluate JavaScript-as-string in the browser
function addCode(js){
  var e = document.createElement('script');
  e.type = 'text/javascript';
  e.src  = 'data:text/javascript;charset=utf-8,'+escape(js);
  document.head.appendChild(e);
}

It will then show up in the sources tab:

enter image description here

Using eval also work by adding the line //# sourceURL=dynamicScript.js at the end

See this plunker

var js = "console.log('this is line 1');\n" +
"//# sourceURL=dynamicScript.js;"
addCode(js); // Right now! Debuggable!

// Dynamically evaluate JavaScript-as-string in the browser
function addCode(js){
  eval(js);
}

Notice that the script is listed under the (no domain) source folder.

Sign up to request clarification or add additional context in comments.

11 Comments

I had seen Phrogz's post, but still did not see how to apply it to the problem at hand. The haystack.js in question is loaded in a <script> tag. So the source has already been eval'd by the time I attempted to Live Edit the soureceURL comment. Am I missing something obvious here? Are you proposing that I somehow re-inject the script back into the page?
Are you trying to capture the eval to see what it does?
If so, just look open dev tools and look at the network tab and releoad the xhr call that loads the script. That will just bring up the page in a source view.
Basically, yes. My goal is to be able to set breakpoints and step through the eval'd code.
Note that with //# sourceURL the space after # is mandatory. I'd also say the sourceURL is the preferred solution, and you should change the order in your answer
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.