Source map for a dynamically created function - javascript

JavaScript allows you to create new functions at runtime with the new Function(...) or eval. Is it possible for a function created in this way to set something like a source map? That is, set the name of the source file from which it was allegedly loaded, as well as different source line numbers.
If there is no general solution, then there may be particular solutions for specific JavaScript engines.

For eval'd code you can simply add:
//# sourceMappingURL=<url>
//# sourceURL=<filename.js>
To the bottom of the code you are evaluating. For the sourceMappingURL, you will send in a data url, since naturally you don't have an existing source map hosted somewhere and you will be dynamically generating it.
Place your original source in the sourcesContent field in the source map, set the file field in the source map to whatever you set in sourceURL, and you should be good to go.
My current attempts at getting this to work in Function constructors is failing, which is a shame- in this case, in both Edge and Chrome, the original source is correctly listed, but it appears that the line number information is broken (the instruction pointer always points to the last line). I am currently investigating this. However, the source map spec does allude to Function constructors containing sourcemaps:
If the generated code is being evaluated as a string with the eval() function or via new Function(), then the source origin will be the page’s origin.
This leads me to believe either I am doing something silly, or there is not great support for this feature.

Related

Extending TestComplete: How to change cursor?

I wrote a TestComplete extension to update Keyword-Test signature from TestComplete in to an external tool.
However, this action takes very long time. That's why I need to change the cursor from arrow to hour glass, and back to arrow after action is done.
The module doing the opperation is writen in js.
If I try to use the following code, suggested by TestComplete code completition
Win32API.SetCursor(Win32API.IDC_WAIT);
I got the error "Object expected". I.e., the js in the TestComplete extension does not know About Win32API object, despite the code completition suggestion.
Ommiting the Win32API. prefix has the same effect. Trying to create appropiate object via
new ActiveXObject("SomeKindClass")
fails, because I am not able to find appropiate name for the class containing some methode to change cursor. (I tryed, Microsoft.Win32, Microsoft.Win32API, Win32, Win32API and some other non-sence names...)
SmartBears description on writing extentions seems to contain no hint about changing the cursor in a js ScriptExtension.
Please appologize, if I overlook it.
Any suggestions are appreciated. Thanx in advice for your F1!
Edit:
A possible way to solve this is described bellow. However, I am not able to follow it to the end, because of lack of time. Perhaps someone can confirm or deny the correctness. That' would be great.
Steps:
Create a new vbs module in the ScriptExtension (or extend an existing one if any).
In
the init method of vbs module, load user32.dll, create prototypes for
the LoadCursor and CreateCursor methods of user32.dll. (See Tutorial)
You call those methods in your setCursor2* methods.
Declare the setCursor2* methods in the Description.xml as method in RuntimeObject of your namespace (See Script Extension Description file)
Call the methods in the js module YourNameSpace.setCursor2Hourglass(); and YourNameSpace.setCursor2Arrow(); respectively.
It is impossible to show an hour glass from a TestComplete extension.
The reason is, following quote, that comes from https://support.smartbear.com/testcomplete/docs/working-with/extending/script/creating/specifics.htm.
"If your design-time action performs actions against the TestComplete
main window (for example, minimizes the window, changes the window
size and position, and so on), an error will occur. This happens due
to specifics of thread organization in TestComplete."
I guess, the "on so on" part includes changing the cursor…

Load multiple D3 maps with similar source code

I built a D3 map that highlights which counties voted for the new governor in my state. I want to build a similar map for another political race using the same code as my governor map. I copied the governor map code and modified it for the other race, changing the geojson file and where the svg will go. I put the other race's code into an external JS file and placed it below my governor JS file in my index.html. Now, depending which file is loaded first in my .html file, one map will appear while the other appears white. Is there anyway I can make both codes different enough to have the maps appear at the same time?
It appears you are writing to the global namespace (In your case, the window object).
When you make the json request through d3, the json file is loaded asynchronously, which means the rest of your javascript code will keep running. This also means that whichever file is being loaded second is overriding all of the variables you just declared, and by the time the json request is processed, the variables (that were declared by the first script) were already overridden by the second script, so each time the json is loaded, you're essentially writing to the same DOM element.
If you want a quick fix, you could just wrap each script in a function and call them onload or use DOMContentLoaded or jquery, but since they are so similar you could just use a single function such as:
function createPoliticalMap(elementID, jsonUrl){
// your code...
//...
var svg = d3.select(elementID).append("svg")
//...
d3.json(jsonUrl,function(error,geodata) {
//...
}
}
And then just do:
createPoliticalMap('#map-gov', 'data/gov.geojson');
createPoliticalMap('#map-ag', 'data/ag.geojson');
Or you could take advantage of JavaScript's object oriented capabilities to define a 'class' of sorts like:
function PoliticalMap(elementID, jsonUrl){
// define your stuff and make the json request based off of the parameters.
}
And do:
var govMap = new PoliticalMap('#map-gov', 'data/gov.geojson');
var agMap = new PoliticalMap('#map-ag', 'data/ag.geojson');
If you wanted to be able to manipulate the D3 graph after creation.
Then adding more political maps becomes trivial, and you could include the code more easily in other pages if you want.

Make source maps refer to original files on remote machine

Using Google Closure Compiler to minify a bunch of javascripts. Now I'd like to also add source maps to those to debug out in the wild.
Thing is, I want to keep the original (and preferrably also the map files) on a completely different place, like another server. I've been looking for a solution to this, and found out about the sourceRoot parameter. But it seems as it's not supported?
Also found this --source_map_location_mapping parameter, but no documentation whatsoever. Seems as it wants a pipe-delimited argument (filesystem-path|webserver-path). Tried a couple of different approaches to this, like local filename|remote url but without prevail. That just gives me No such file or directory and java.lang.ArrayIndexOutOfBoundsException.
Has anyone succeeded to place the minified/mapped source files on a remote machine?
Or does anyone know of any documentation for --source_map_location_mapping?
Luckily Google Closure Compiler's source code is available publicly
https://gist.github.com/lydonchandra/b97b38e3ff56ba8e0ba5
REM --source_map_location_mapping is case SENSITIVE !
REM need extra escaped double quote --source_map_location_mapping="\"C:/tools/closure/^|httpsa://bla/\"" as per http://stackoverflow.com/a/29542669
java -jar compiler.jar --compilation_level=SIMPLE_OPTIMIZATIONS --create_source_map=C:\tools\closure\latest\maplayer.js.map --output_wrapper "%output%//# sourceMappingURL=maplayer.js.map" --js=C:\tools\closure\mapslayer.js --js_output_file=maplayer.min.js --source_map_location_mapping="\"C:/tools/closure/^|httpsa://bla/\""
The flag should be formatted like so:
--source_map_location_mapping=foo/|http://bar
The flag should be repeated if you need multiple locations:
--source_map_location_mapping=foo/|http://bar --source_map_location_mapping=xxx/|http://yyy
But what I expect that you are running into is that the "|" might be interpreted by your command shell. For example:
echo --source_map_location_mapping=foo/|http://bar
-bash: http://bar: No such file or directory
(The choice to use "|" was unfortunate). Make sure it is escaped appropriately. like:
--source_map_location_mapping="foo/|http://bar"
I submitted a pull request to report an error for badly formatted flag values:
https://github.com/google/closure-compiler/pull/620
which will at least you know that your flag value is incorrect (so you won't see the out of bounds exception).
John is correct functionality-wise, but I think I can clear it up a bit (as this was super confusing for me to get working).
I suspect many people have the same issue as I:
source map urls are generated relative to your current directory
they don't necessarily match up to relative urls on your website/server
Even if they did match up directly, the strangely-defined pseudo-spec found here means that Chrome/Firefox are going to try to load your paths relative to your sourcemap. i.e. the browser loads /assets/sourcemaps/main.map, sees assets/js/main.js, and loads /assets/sourcemap/assets/js/main.js (yay). (Or it might be relative to the original js file actually, I just happened to have them in the same directory).
Let's use the above example. Say we have assets/js/main.js in our sourcemap, and want to make sure that loads mywebsite.com/assets/js/main.js. To do this, you'd pass the option:
--source_map_location_mapping="assets|/assets"
Like John mentioned, quotes are important, and repeat the arg multiple times for multiple options. The prefixed / will let Firefox/Chrome know you want it relative to your website root. (If you're doing this in something like grunt-closure-tools you'll need to escape more:
config:{
source_map_location_mapping:"\"assets|/assets\"",
}
This way, we can essentially map any given sourcemap path to any given website path. It's not really a perfect replacement for some sort of closure source root, but it does let you map each section of your sources individually to their own roots, so it's not that bad a compromise, and does give some additional flexibility (i.e. you could specify some cdn paths for some of your assets but not for other).
An additional thing you might find helpful, you can automatically add the sourceMappingURL via an output_wrapper. (Though, if you want the ability to debug in production, you should probably prefer some ability to make the server return X-Sourcemap: blah.js.map headers instead, inaccessible by the public)
--output_wrapper="(function(){%output%}).call(this); //# sourceMappingURL=/assets/js/my_main_file.js.map"

How do I get the path of the currently running script with Javascript?

We have an IE extension implemented as a Browser Helper Object (BHO). We have a utility function written in C++ that we add to the window object of the page so that other scripts in the page can use it to load local script files dynamically. In order to resolve relative paths to these local script files, however, we need to determine the path of the JavaScript file that calls our function:
myfunc() written in C++ and exposed to the page's JavaScript
file:///path/to/some/javascript.js
(additional stack frames)
From the top frame I want to get the information that the script calling myfunc() is located in file:///path/to/some/javascript.js.
I first expected that we could simply use the IActiveScriptDebug interface to get a stacktrace from our utility function. However, it appears to be impossible to get the IActiveScript interface from an IWebBrowser2 interface or associated document (see Full callstack for multiple frames JS on IE8).
The only thing I can think of is to register our own script debugger implementation and have myfunc() break into the debugger. However, I'm skeptical that this will work without prompting the user about whether they want to break into the debugger.
Before doing more thorough tests of this approach, I wanted to check whether anyone has definitive information about whether this is likely to work and/or can suggest an alternative approach that will enable a function written in C++ to get a stack trace from the scripting engine that invoked it.
Each script you load may have an id and each method of the script calling myfunc() may pass this id to myfunc(). This means that first you have to modify myfunct() and finally alter your scripts and calls.
This answer describes how I solved the actual issue I described in the original question. The question description isn't great since I was making assumptions about how to solve the problem that actually turned out to be unfounded. What I was really trying to do is determine the path of the currently running script. I've changed the title of the question to more accurately reflect this.
This is actually fairly easy to achieve since scripts are executed in an HTML document as they are loaded. So if I am currently executing some JavaScript that is loaded by a script tag, that script tag will always be the last script tag in the document (since the rest of the document hasn't loaded yet). To solve this problem, it is therefore enough just to get the URL of the src attribute of the last script tag and resolve any relative paths based on that.
Of course this doesn't work for script embedded directly in the HTML page, but that is bad practice anyway (IMO) so this doesn't seem like a very important limitation.

Run time error handling on lazy loaded javascript?

Does anyone have any ideas how to do error handling on lazy loaded javascript? I am using an approach in which an ajax request is called and the code is eval'd in global scope. When a runtime error is struck, it spits out the filename as my lazy loading script and the line number is the error line plus the line number of my eval in my loading script. This wouldn't be so bad except all the javascript files get combined into modules for sections of the site. A try catch around the javascript file itself wont catch runtime errors of the functions. Any ideas? Window.onerror doesn't provide the correct filename so it is out of the question. I need to catch it before it is hit.
I was thinking maybe I could programmatically include try catches around all the functions within the eval'd code (which is ugly), but since it is done at the window level I am not sure how to access the eval'd code specifically and dynamically. Sure if the javascript is an object named "Bob" I can access window.Bob but I need to do it dynamically.
I solved the issue, however it is not the most elegant solution. Essentially what I do is this:
1. After the site loads I look at all the objects that are in window and push them into an array. This basically says to my code, ignore these objects.
When I modularize my code I keep track of the length of the files and fileNames being place into a module.
The last line of the modulizer takes the fileLength array and lineLengths and calls a function in my error handling object;
The error handling code finds new objects in window. If they exist, set a property to match fileLengths and fileNames;
Recurse through the new objects and add decorate the functions to have try catches around them.
When one of those catches is hit, traverse upward and find the properties.
Calculate the file and line number based on the properties.
Output the new error based on the correct file and line number;
Yes ugly... but it works.

Categories

Resources