Facebook's JS SDK has recently started using newer ES5 Javascript methods such as Object.keys() and [].map(). They still support older browsers by having an ES5() function that accepts the original object, the name of the desired method, and any parameters. It then runs either the native method or an equivalent JS method if the native one isn't available. For example:
ES5(g.api.whitelist, 'forEach', true, function(ca) {
s[ca] = 1;
});
or for top-level objects,
ES5('JSON', 'parse', false, r.responseText);
I suspect that this is the result of a preprocessor, and FB's devs are actually writing something more along the lines of
g.api.whitelist.forEach(function(ca) {
s[ca] = 1;
});
and
JSON.parse(r.responseText);
(presumably with longer variable names too)
Now, assuming I'm right that there is a preprocessor, is the ES5() function and associated preprocessed are an open-source project or something in-house? If it's in-house, can anyone from FB comment on the possibility of open-sourcing it? It's something that I could find tremendously useful.
We are indeed using a preprocessor (based on jspatch) which lets us write regular ES5 code. The ES5 function itself is basically a wrapper around polyfills from MDN and JSON3.
Not only does this let us write ES5, but it avoids us using faulty implementations of things like Function#bind and JSON.stringify.
The blog post is now out.
Searching Facebook's open-source github repositories does not show any ES5 methods. I explicitly checked out and recursively grepped the ones that mention javascript. So it does not appear that what you are seeing is publicly available from them. I could not find it anywhere else either.
If you need ES5 backwards compatibility, have a look at this es5-shim
http://connect.facebook.net/en_US/all.js
is this what you want? it doesnt list any licenses in the file and it seems to be autogenerated?
https://github.com/facebook/connect-js/
?
this would point to "yes" and the license would be apache?
Related
I am trying to import array from js file to another js file. link For example:
file1.js:
var array = ['one', 'two', 'three'];
file2.js:
import { array } from 'file1'
My idle says that "import declaration are not supported by current Javascript version." How can I import this array?
Thank You for any help
As mentioned by article you linked, import is available with ES6.
I think you're writing ES5 JavaScript, then you'll need a ES6 transpiler such as Babel.
https://codeburst.io/es5-vs-es6-with-example-code-9901fa0136fc
importing is only allowed in ES6, the newest version of javascript so to speak. Browsers are just now getting around to being able to "understand" ES6, and they won't be able to understand it completely for awhile. Currently, browsers understand the previous version of javascript, ES5, really well. So how can you write code that uses import since it's ES6?
Unfortunately, you need some special tools that change code that you write in ES6 to ES5 so that browsers can understand your code. This is called transpiling. A tool called Babel is by far the most popular transpiler used today. But that's not all. You'll need another tool to bundle the modules you write in ES6 syntax. Rollupjs and Webpack are the most popular tools for this task.
It can take a few weeks of reading and trying things out to learn these tools, so unfortunately I can't explain them well enough in one answer here for you to get a complete understanding. Basically what bundling does, using your example: file1.js and file2.js will be combined into one single final file bundle.js and this is the file that you will include <script src="bundle.js"> in your html. file2.js is called a module. How does this new help write better code? Well we can write most of our code in modules and then just import whatever modules I need on particuler pages. If I need a countdown timer on page1.html, I'll create a module which has the code needed for a countdown timer, and import the countdown timer module. If I need a countdown timer on a new page 6 months from now, I will just import the countdown timer module on this new page. Code reusability.
Webpack is more popular than Rollup, but I would recommend using Rollup to get a good overview of what a bundler actually does. We use Rollup in our enterprise application in fact, although Webpack is more widely used I think, as it does many many things beyond bundling.
Note: ES6 is not really the newest version of javascript; we already have ES7 and ES8 coming along. In fact, there are new features constantly being added to the official javascript language. The problem is that it takes time for browsers to implement (be able to "understand") these new features.
The best way I can think to replicate the behavior in ES5 is to create an iframe with a script tag to the file you want. Onload you can grab the desired variable and bring it into the parent window. Then destroy the iframe.
Usage would be something like this:
import('file-url', 'variable-name', function(imported){
});
Implementation would be something like this:
function import(filePath, varName, callback){
//create iframe
//create script tag
//add filepath and onload handler
script.onload = function(){
//retrieve variable and
//trigger callback in parent
};
}
I am currently trying to figure out why JSDT posts errors like 'JavaScript error on valid regex'.
While I was testing I realized that it works fine for simple files like this:
var a = {
urlParseRE: /^\s*(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:#\/#\?]+)(?:\:([^:#\/#\?]+))?)#)?(([^:\/#\?\]\[]+|\[[^\/\]##?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/,
test: b.replace(/^\/|(\/[^\/]*|[^\/]+)$/g, "")
};
and reports errors on complex files like jQuery.mobile-1.3.1.min.js.
I used online tool to format mimified jQuery script and then deleted almost all content out of it to make a simple example which would help to replicate the problem. When size of file was reduced from around 3000 to 300 lines some new validation errors were posted before original one above. I ended up my experiment with completely different problem. Validation error was posted on ',' in example below:
!function(){
window.alert("passed 1");
}(),
function(){
window.alert("passed 2");
}();
window.alert("passed 3");
I understand that JSDT project was dormant for a while and supports only ECMAScript v3 so before I create new issue I'd like to be sure this last simple js example is correct for ECMAScript Language Specification 3rd edition. Is there any online or offline tool to verify that?
A little dated, but https://jshint.com/ points out ES3 and ES5 issues
You can use Esprima for this.
"ECMAScript parsing infrastructure for multipurpose analysis"
If you feed your last chunk to Esprima's validator, it says that "Code is syntatically valid."
Esprima follows ES5, so technically it could pass ES5-related syntax which ES3-only-compliant parser will not understand.
But in this case I don't see anything related to ES5, so it must be a bug in JSDT.
If you are open to using a command line tool, then I would recommend es-check (NPM link). You can test if your JS code conforms to the standard you specify. For example to check if index.js conforms to ES5 you can run:
es-check es5 index.js
Or if you want to check all scripts within a directory you could run:
es-check es5 './scripts/**/*.js'
I am currently working on an old project with ton of legacy code.
A syntax I have never met is used to access a specific id in the dom in javascript.
Instead of using document.getElementById("btnsubmit"), $('btnsubmit') is used.
I have never met this syntax. Moreover it seems that firebug doesn't like it either as it seems to break the debugger. I have issues where the code doesn't seem to be executed in a debugging environment although this code is used on a production site and seems to work.
Does any one have a reference on this syntax? Where does it comes from, is it deprecated?
It's from a javascript library, and in general it's more modern than getElementById. You need the script include though.
Your example looks like Prototype
$ is just a regular character in javascript and it is often used by javascript libraries and defined to be a function name so that $() is just a function call. In some cases, $ might be defined to be a synonym for document.getElementById() as shorthand to save typing and in other cases, it's a more robust CSS3 style selector engine (as in the jQuery library).
In either case, if its undefined in your code, then you are probably missing a library reference that your code relies on. You will need to find out what library your code was written to use and make sure that library is included in the code before this spot so that the $() function is defined properly.
I wish to use knockout.js, but unfortunately I cannot use jquery-tmpl due to the prequisite of jquery 1.4.2, which (I won't go into it here) we cannot upgrade to.
Has anyone got any tips on getting started using Mustache templates with knockout? I've been finding it tricky to find any information regarding it.
Update I've released initial version of template engine for knockout js that is using mustache as a template library. You can check it out at https://github.com/WTK/ko.mustache.js
Have you seen this part of documentation http://knockoutjs.com/documentation/template-binding.html ? Especially take a closer look at the Note 8 which points you to check the jqueryTmplTemplateEngine.js in the knockout source code (to spare you the effort of searching, its this one: https://github.com/SteveSanderson/knockout/blob/master/src/templating/jquery.tmpl/jqueryTmplTemplateEngine.js).
I just took a glance at source of that file, but everything seems to be quite simple. You have to define couple of callback functions that are (I assume) called by knockout js when needed.
Those functions include:
function renderTemplateSource(templateSource, bindingContext, options) {}
function createJavaScriptEvaluatorBlock(script) {}
function addTemplate(templateName, templateMarkup) {}
Check what those functions return when using jquery.tmpl and try to mimic their behavior whilst using moustache instead.
Would it be possible to sandbox user-submitted Javascript by overriding various functions such as alert, window.location, and eval?
I'm not looking for a perfect solution. I'm sure some people would still find a way to rearrange divs to spell out swear words or something malicious, but if I could disable page redirects 100% reliably I would be mostly happy.
I tried in Chrome, and doing something like
context={}; //use this to prevent `this` from being `window`
context.f=function(){
var window=null,location=null,eval=function(){};
console.log(window); //also the other two
};
context.f();
seems promising. If I replace the console line with user-submitted code (checking for paren balancing), would that be an absurdly bad idea or a mildly bad idea? On Chrome I can still break things by going through this to Function and redefining things, but that would be acceptable to me.
You can use Microsoft Web Sandbox or Google Caja.
Here are two more possible solutions (disclaimer: I just started looking for this myself, so I am not an expert).
This is very interesting, uses web workers to sandbox untrusted code:
https://github.com/eligrey/jsandbox
even though, I wonder if that is maintaned anymore, or if the following html5 "sandbox" iframe attribute supersedes it:
http://www.w3schools.com/html5/att_iframe_sandbox.asp
vm.js is a javascript virtual machine implemented in pure coffeescript(should run in relatively old browsers) and can be used as a lightweight in-process sandbox. It can break infinite loops and shields global objects from modifications.
Depending on what this needs to do, you could always run the javascript in a document-context-free environment, like through Rhino, and then grab the results server-side and clean/insert those.
You could also try Douglas Crockford's AdSafe, though it does limit the possibilities of JavaScript.
Masking the globals with local variables is not secure actually. Preprocessing the untrusted code with tools like Google Caja may help, but it's not necessary:
For a web-browser simply running a code in a Worker is enough - it seems to be pretty restricted nowadays. See update below
For Node.js you may fork() in a sandboxed process and execute the code there (using the child_process module).
There are also some libraries for simplifying the sandboxing, one of those created by myself is Jailed (there's also a demo with JS-Console which executes user-submitted code in a sandbox).
Update: obviously I was wrong, the worker is not secure by itself, as it can access some of same-origin stuff, like IndexedDB for instance. I have submitted a related question. The solution is to additionally put the worker into a sasndboxed iframe, which is also implemented in my Jailed library.
Use HTML5 "sandbox" iframe attribute.
I made a javascript function for this.
function evalUnsafe(userCode) {
var vars = [];
var legal = {console: 'console', alert: 'alert'};
for(var b in this) {
if (!(b in legal)) {
vars.push(b);
}
}
var funcs = vars.join(",");
var code = "(function sandbox(" + funcs + ") {function runthis() {eval(" + JSON.stringify(userCode) + ");};var a = new runthis();})();";
eval(code);
}
And then you can do this
Example 1:
evalUnsafe("alert(window);");
Example 2 (from a php file):
evalUnsafe(<?php echo json_encode(file_get_contents("example.js"));?>);
You can download it from here:
https://github.com/oyvindrestad/javascriptsandbox