15

Let's say you would get a bunch of .js files and now it is your job to sort them into groups like:

  • requires at least JavaScript 1.85
  • requires at least E4X (ECMAScript 4 EX)
  • requires at least ECMAScript 5

or something like this.

I am interested in any solution, but especially in those which work using JavaScript or PHP. This is used for creation of automated specifications, but it shouldn't matter - this is a nice task which should be easy to solve - however, I have no idea how and it is not easy for me. So, if this is easy to you, please share any hints.

I would expect something like this - http://kangax.github.com/es5-compat-table/# - just not for browsers, rather for a given file to be checked against different implementations of JavaScript.

My guess is, that each version must have some specifics, which can be tested for. However, all I can find is stuff about "what version does this browser support".


PS: Don't take "now it is your job" literally, I used it to demonstrate the task, not to imply that I expect work done for me; while in the progress of solving this, it would be just nice to have some help or direction.


EDIT: I took the easy way out, by recquiring ECMAScript 5 to be supported at least as good as by the current FireFox for my projekt to work as intendet and expected.

However, I am still intereseted in any solution-attemps or at least an definite answer of "is possible(, with XY)" or "is not possible, because ..."; XY can be just some Keyword, like FrameworkXY or DesignPatternXY or whatever or a more detailed solution of course.

Jook
  • 4,564
  • 3
  • 26
  • 53
  • 5
    *“and now it is your job”* That attitude is not going to get very many answers. – Waleed Khan Mar 11 '13 at 11:43
  • yes, i know, but it is not really my "job", and something not easy to find, i am working on this and will provide an answer myself, if and when i find one. This here http://stackoverflow.com/q/11707698/1370465 was close to it, but i think i does not apply here - or does it? – Jook Mar 11 '13 at 11:46
  • 2
    @WaleedKhan Jook didn't literally mean that it's our job to do this work for him/her, they were describing the situation they're in. – John Topley Mar 11 '13 at 12:02
  • 1
    a good library is bundled with unit-tests, that's what they are for. Some document compatibility issues , that are not related to javascript version per say , but how the DOM api is implemented on each browser. That's why usually , javascript version is irrelevant. what matters is the API used. – mpm Mar 11 '13 at 12:08
  • @mpm I don't quite get what you wrote, but look here: https://www.inkling.com/read/javascript-definitive-guide-david-flanagan-6th/core-javascript-reference/object-isfrozen -> wouldn't this mean, i could check for usage of Object.isFrozen() in a .js file and mark it as ES5, as it clearly would require it? – Jook Mar 11 '13 at 12:12
  • and what if the developer uses its own isFrozen defined function ? it may be unlikely but it doesnt mean he is actually using ES5. In my libraries i have my own Object.create for instance. – mpm Mar 11 '13 at 12:17
  • @mpm ok, now i get it - but let's say one would get an undocumented piece of websoft, is there no tool around to at least indicate, which version it could or should be? Wouldn't this be quite a workload otherwise? I mean, if you check what the browser does support, how do you know it is enough? Manually check every used function?! – Jook Mar 11 '13 at 12:26
  • 1
    Browsers tend to pick and choose what JS features to implement. Not one browser supports *all* of ECMAScript 5, JavaScript 1.8, etc. So detecting a js document's conformance to a certain JS version, is not that helpful. To make your JS as browser compatible as possible, you should be using [feature detection, not browser detection](http://stackoverflow.com/questions/1294586/browser-detection-versus-feature-detection), let alone detection of the JS version being used. – Web_Designer Mar 19 '13 at 05:26

2 Answers2

3

Essentially you are looking to find the minimum requirements for some javascript file. I'd say that isn't possible until run time. JavaScript is a dynamic language. As such you don't have compile time errors. As a result, you can't tell until you are within some closure that something doesn't work, and even then it would be misleading. Your dependencies could in fact fix many compatibility issues.

Example:

  • JS File A uses some ES5 feature
  • JS File B provides a shim for ES5 deficient browsers or at least mimics it in some way.
  • JS File A and B are always loaded together, but independently A looks like it won't work.

Example2:

  • Object.create is what you want to test
  • Some guy named Crockford adds create to Object.prototype
  • Object.create now works in less compatible browsers, and nothing is broken.

Solution 1:

  1. Build or find a dependency map. You definitely already have a dependency map, either explicitly or you could generate it by iterating over you HTML files.
  2. Run all relevant code paths in environments with decreasing functionality (eg: ES5, then E4X, then JS 1.x, and so forth).
  3. Once a bundle of JS files fail for some code path you know their minimum requirement.
  4. Perhaps you could iterate over the public functions in your objects and use dependency injection to fill in constructors and methods. This sounds really hard though.

Solution 2:

  1. Use webdriver to visit your pages in various environments.
  2. Map window.onerror to a function that tells you if your current page broke while performing some actions.
  3. On error you will know that there is a problem with the bundle on the current page so save that data.

Both these solutions assume that you always write perfect JS that never has errors, which is something you should strive for but isn't realistic. This might; however, provide you with some basic "smoke testing" though.

Parris
  • 17,833
  • 17
  • 90
  • 133
  • thank you for the early answer and solution proposal, you have my +1, but @ben336 made it quite clear to me, why I shouldn't handle this problem as I thought I could. – Jook Mar 25 '13 at 08:34
2

This is not possible in an exact way, and it also is not a great way of looking at things for this type of issue.

Why its not possible

Javascript doesn't have static typing. But properties are determined by the prototype chain. This means that for any piece of code you would have to infer the type of an object and check along the prototype chain before determining what function would be called for a function call.

You would for instance, have to be able to tell that $(x).bind() o $(x).map are not making calls to the ecmascript5 map or bind functions, but the jQuery ones. This means that you would really have to parse out the whole code and make inferences on type. If you didn't have the whole code base this would be impossible. If you had a function that took an object and you called bind, you would have no idea if that was supposed to be Function.prototype.bind or jQuery.bind because thats not decided till runtime. In fact its possible (though not good coding practice) that it could be both, and that what is run depends on the input to a function, or even depends on user input. So you might be able to make a guess about this, but you couldn't do it exactly.

Making all of this even more impossible, the eval function combined with the ability to get user input or ajax data means that you don't even know what types some objects are or could be, even leaving aside the issue that eval could attempt to run code that meets any specification.

Here's an example of a piece of code that you couldn't parse

var userInput = $("#input").val();

var objectThatCouldBeAnything = eval(userInput);

object.map(function(x){
   return !!x; 
});

There's no way to tell if this code is parsing a jQuery object in the eval and running jQuery.map or producing an array and running Array.prototype.map. And thats the strength and weakness of a dynamically typed language like javascript. It provides tremendous flexibility, but limits what you can tell about the code before run time.

Why its not a good strategy

ECMAScript specifications are a standard, but in practice they are never implemented perfectly or consistently. Different environments implement different parts of the standard. Having a "ECMAScript5" piece of code does not guarantee that any particular browser will implement all of its properties perfectly. You really have to determine that on a property by property basis.

What you're much better off doing is finding a list of functions or properties that are used by the code. You can then compare that against the supported properties for a particular environment.

This is still a difficult to impossible problem for the reasons mentioned above, but its at least a useful one. And you could gain value doing this even using a loose approximation (assuming that bind actually is ecmascript5 unless its on a $() wrap. Thats not going to be perfect, but still might be useful).

Trying to figure out a standard thats implemented just isn't practical in terms of helping you decide whether to use it in a particular environment. Its much better to know what functions or properties its using so that you can compare that to the environment and add polyfills if necessary.

Ben McCormick
  • 25,260
  • 12
  • 52
  • 71