Headless single-source library for JVM and JavaScript - javascript

I need to write a library that can be compiled to Java-classes (to be more specific: Android) and JavaScript or TypeScript (modern Browser and Node.js).
The lib will deal with lists of objects with a lot of numbers and has to calculate statistics and filter/manipulate the lists. No rocket-science, dependencies can be bridged for each environment. No problems with decimal arithmetics. (=> The libs could be developed in TypeScript and Java, but nobody wants to maintain 2 semantically equal sources.)
I've no fear to learn a new language, but integration should be smooth (i.e. create a .jar with standard Java interface and Java types and a .js file for JavaScript/TypeScript without hundreds of kilobytes of runtime).
Could I choose Scala/Scala.js for this?
Would it work with Kotlin?
Has anybody of you guys managed an equal task successfully? What are the caveats?

Well, the basics are very normal for Scala/Scala.js these days -- many libraries cross-compile with no changes. The Scala.js compiler is highly optimized, and only includes code that is actually invoked, so the output is reasonably lean. (Unless you need bulky external dependencies, which the SJS compiler can't do much about.)
Managing the dependency differences will be some extra effort, if you need to deal with them differently on the two sides. This isn't terribly unusual for Scala/Scala.js, but does require that the project be structured for that. The documentation of CrossProject gets into the details.
But overall -- yeah, that's all fairly common at this point...

Related

Can you compile JS code using V8 and feed that directly to Chrome?

I'm looking for a way to protect some javascript code from reading/modifying. I know many people consider that impossible, but still...
From what I see the Chrome's V8 engine does a number of optimizations when it sees JS code, probably compiles it (?) and then runs it.
So I'm wondering is it possible to use V8's C++ api to compile the JS code into machinecode/chromecode and then feed that directly into Chrome (I don't care about other browsers)?
Supposedly it will not only be faster, but also non-humanly readable, something like ASM.
Is this possible?
WebAssembly is doing this thing so I don't understand why we can't do it with JS code.
There's also EncloseJS and pkg that are doing a very similar thing.
V8 developer here. No, it is not possible to compile JavaScript ahead of time and send only the compiled code to the browser. V8 (and other virtual machines like it) contain compilers, but they cannot be used as standalone compilers to produce standalone binaries.
In theory, you could compile JavaScript to WebAssembly -- any two turing-complete programming languages can in theory be compiled to each other. As far as I know, no such compiler exists today though. One big reason for that is that performance of the end result would be horrible (see the discussion with Andreas Rossberg for details); so considering that browsers can execute JavaScript directly, people have little reason to develop such a thing. (It would also be a large and difficult task.)
As for your stated goal: your best shot at making JavaScript code unreadable is to minify it. In fact, that is effectively just as good as your idea to generate assembly, because disassemblers exist that turn assembly back into minified-like higher-level language code; they cannot reconstruct variable names or comments (because that information is lost during compilation), but they can reconstruct program logic.
What I ended up doing is moving some of the logic from JavaScript into C++ and compiling that into NodeJS native modules (that's possible for Electron apps).
It works pretty good, it's very fast, the source is... as protected as it can get, but you may need to worry about cross-platform issues, also compiling/linking can be a bit of a pain, but other than that it's great.
WebAssembly is not doing that. And no, it's not possible either. The web is supposed to be both browser- and hardware-independent.
Moreover, a language like JS would not be faster if compiled offline -- it only is anything close to fast because it is dynamically compiled and optimised, taking dynamic profile information into account.

What do those javascript front-end build tools mean when they say "compile" my js codes?

I saw those javascript front-end build tools, e.g. webpack, using the word "compile" from time to time. I am not sure what does compile javascript codes mean exactly, at least not like compile c/c++ codes.
I think I understand the "build" process in general, like bundle all js codes into one big file, minify/uglify the codes, using babel to transforms ES6 syntax(transpile). But what does compiling mean here, how does it fit in the whole building process or it is just another name for the whole build process?
Currently, I thought it may be just another name for using Babel to transforms ES6 syntax.
PS. after reading this SO Is Babel a compiler or transpiler? I believe my question is not same as that. Because it is not just related to Bable. For example, webpack also uses the term compiler https://webpack.js.org/api/compiler/ I do not understand its meaning there!
Browserify uses compiler as well e.g, https://github.com/robrichard/browserify-compile-templates "Compiles underscore templates from HTML script tags into CommonJS in a browserify transform"
It's better to describe the process as "transpilation."
Javascript always executes in a specific environment: in Chrome and Electron, it's the V8 engine; in Firefox, it's SpiderMonkey; etc. Each of these engines supports a specific set of language features and not others. As an example, some engines only support var and do not support const or let. Some support async/await, and others only support Promise.
But web developers know about these other features, and they want to use them, even when they're writing for an engine that doesn't support those features. Why? Most new language features are designed with the goal of making it possible to express complicated concepts in simpler and cleaner ways. This is extremely important, because the number one job of code is to make its purpose clear.
Thus, most language features are essentially syntactic sugar for existing functionality. In those cases, it's always possible to express a routine using both new and old syntax. This is a logical necessity.
A transpiler like Babel can read a script written using advanced syntax, and then re-express the script using a restricted set of language features. Relying on an intermediate representation called an abstract syntax tree, it can produce code that is guaranteed to be functionally equivalent, even though it does the work using very different, more widely-supported control structures.
Perhaps we web developers have gotten lazy in our terminology. When we talk of "compiling" javascript, we aren't usually talking about converting the script to something like bytecode. We're talking about transpilation.
Other kinds of build tasks are also becoming quite common. These days, the front-end is obsessed with a million flavors of "templating," because it's extremely tedious and confusing to describe DOM changes using pure javascript, and because application complexity is increasingly very rapidly. Some frameworks require you to convert source code to other intermediary forms that are later consumed by the web application at runtime. Others permit devs to describe UI using invented syntaxes that no browser is even attempting to support natively. Which tasks are needed varies by application depending on which frameworks are being used, the particulars of the application architecture, and the contours of the deployment environment, and that's just a start.
At its foundation, a web page is built using HTML, CSS, and javascript. That much hasn't changed. But today, most serious applications are built almost entirely in javascript (or something very much like it) and sass. Building the application is the process of applying a set of transformations to the source code to yield the final artifacts in those three bedrock languages.
We lump all that stuff under the term "compile."
You pretty much hit the nail on the head. When the Compile (or more appropriately transpilation) operation happens on a JavaScript project it can mean a number of things. As you mentioned these could range from minification, applying polyfills, shims, or the literal act of "compiling" the scripts into a single bundle file for platform/browser consumption.
Transpilation when using super sets of the JavaScript language such as TypeScript, ActionScript, or UnityScript describes the process of converting the source x-script back into native JavaScript which can be in turn be interpreted by a browser (since the browser doesn't recognize the superset languages).
However you are absolutely correct. We aren't compiling our JavaScript into binary, but the term gets thrown around a lot which can lead to confusion. All that said, we are closing in on the age of adoption of WebAssembly and ASMJs which promises to bring the age of bytecode running in the browser which will bring about some interesting possibilities, but alas... That's a story for another day ;)
You're right when you say these front-end Javascript tools don't use the word compile in same context in what your used to with build tools for languages like C/C++. C/C++ compilers turn source code into machine code.
These JavaScript build tools-- like Webpack-- use the word compile in a sense thats more metaphorical than conventional.
When web build tools use the word compile, they're using it in the sense that they are transpiling, minifying (a.k.a uglyfying), and bundling the source files so they are better optimized for client browsers and network requests. (Smaller file sizes, better browser compatibility, less HTTP requests from bundled assets, etc.)

Angular2 application half in Typescript and Javascript

I currently have a large JavaScript application with a lot of code written in vanilla Javascript for a specific platform for where I work.
I need to transform this into a web application I can open in the browser. This should be able to be done relatively easy by swapping out the components from my current application to the components of another web technology.
However since Angular2 is written in TypeScript, if I was to choose it as the framework I use, should I really also be rewriting the rest of my non-component JavaScript to TypeScript to or will I not need to do this.
Would it be a bad idea to have an application which was half TypeScript and half JavaScript like this?
It's not a bad idea to mix TypeScript and JavaScript. I do it every day. But you have to now that it may be very painful in some cases. So I can only advice to enforce migration to TypeScript as fast as possible.
I would suggest you to read this introduction to migration from JavaScript to TypeScript: https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html
This might also be a valuable source: https://basarat.gitbooks.io/typescript/content/docs/types/migrating.html but I have the impression that the author has a very narrow opinion on how to work with typescript so just don't take everything there as it is, but just as a suggestion.
There are also a lot of other resources about migrating from JavaScript to TypeScript.
For the last month of migration to TypeScript I can say, that in many cases you can simply change your JavaScript to a TypeScript file and add exports. Than you need to add the needed imports in the other places and everything works just like before.
If you can make sure, that you only use old JavaScript in your TypeScript and not the other way round you can split your project into to packages. Load the JavaScript into global as done before and than create Typings for the parts of your JavaScript you use in TypeScript.

Managing a large codebase in Node.js

I am about to embark on a Node.js project with a fairly large codebase. I would prefer to keep my code separate from node_modules.
I would ideally like to work with namespaces and folders as I think it would be a nice way to manage things. However, assuming I have read correctly, this would mean that I would have to import any files/"classes" I require using the path to the file which would be quite messy and hard to manage.
What is the defacto method for managing a large amount/ of code for a Node.js project?
My advice is to use a static typed language, since they provide automatic functionality which helps managing large codebases. That could for example be dart, typescript or coffeescript, all being able to produce javascript.
This post explains well the benefits (especially compared to JS):
http://arstechnica.com/information-technology/2014/06/why-do-dynamic-languages-make-it-difficult-to-maintain-large-codebases/
Some of the main problems stated in the linked article:
There is no modularization system; there are no classes, interfaces,
or even namespaces. These elements are in other languages to help
organize large codebases.
The inheritance system—prototype
inheritance—is both weak and poorly understood. It is by no means
obvious how to correctly build prototypes for deep hierarchies (a
captain is a kind of pirate, a pirate is a kind of person, a person is
a kind of thing...) in out-of-the-box JavaScript.
There is no
encapsulation whatsoever; every property of every object is yielded up
to the for-in construct, and is modifiable at will by any part of the
program.
There is no way to annotate any restriction on storage; any
variable may hold any value.
If you started with JS and don't want to abandon your current code base, you could switch to typescript.
Shortly before my JS project reached 5000 lines of code (in about 15 files), I moved it to typescript. It took me about 4 hours to get it back to running.
This post gives some insights from someone movig Node.js to a typescript environment:
http://tech.kinja.com/my-experience-with-typescript-710191610

F# / Clojure to Javascript: interaction with environment and javascript libraries

I've been looking at (mostly) functional languages that can convert to Javascript, and these two stand up top nowadays. But I have two doubts about them, (talking about ClojureScript and Pit for F#):
I suppose that, as both just translate the original language, the moment one makes a call to anything .Net or Java, the program can't directly compile to Javascript. Am I right with this? If so, in this case the ability to interact with the Java/.Net environments is "dangerous".
As far as I know ClojureScript can interact with any JS library out there (node.js, jquery, etc), whereas in Pit they are developing "extensions" to allow this... so I assume importing ANY js library is not supported. I read in SO that WebSharper does support this, but there isn't much evidence and is closed source. So, in practice, how is actually the state of any JS interaction from both languages?
Thanks a lot!
I'm not familiar with ClojureScript, but I can answer some of your questions about Pit (and WebSharper).
Calling .NET libraries
Pit only translates explicitly marked F# code, so when you call standard .NET library or some F# library that does not support Pit, it is not going to work (unlike Microsoft Live Labs Volta project, which is now dead).
However, you can re-implement any such library in F# and tell Pit to use that implementation instead - if the functionality is a part of standard F# library, you can even copy the source code from the open-source F# release. In practice, I don't think this is such a big issue, because most of the .NET libraries are specific to servers or desktops and so you probably won't need that many of them.
Calling JS libraries
Since F# is a statically typed language, it requires to know types of things that you're working with. In Pit and WebSharper, these are obtained by defining F# types (with no implementation) that then get mapped to JavaScript. In Pit, these have to be written by hand, although my guess is that in F# 3.0, this could be done automatically using F# type providers. I believe WebSharper has a tool for that, but it is only available as part of the commercial release.
Interop with JavaScript is not a problem in WebSharper. We ship a lot of bindings to existing JS libraries, and if any functionality is missing, you can recover it fairly quickly in F# with code like this:
[<Direct "jQuery($x).hide()">]
let hide (x: obj) = ()
The challenge in F# is type safety - how much type safety and precise code completion are you willing to retrofit on top of the untyped (and often untypeable!) JavaScript libraries. I never used ClojureScript, but I imagine this is not even a question there since Clojure is untyped as well.
Interop with the underlying .NET platform is indeed "dangerous". As Tomas points out, WebSharper requires that all JavaScript-callable functions are annotated. We have worked around this limitations for some standard classes (strings, collections such as dictionaries, maps and sets), but the support is far from complete.
With WebSharper you can run .NET code on the server and use it via AJAX fairly transparently:
[<Remote>]
let add (x: int) (y: int) = async.Return(x + y)
[<JavaScript>]
let remoteAdd () =
async {
let! sum = add 1 2
return JavaScript.Log("RESULT", sum)
}
|> Async.Start
Unfortunately, if you do have to run large .NET libraries on the client this is not a solution, and you probably have to look in the direction of Silverlight instead.
Disclaimer - I am developing WebSharper, so my input is obviously biased. That being said, when choosing between WebSharper and Pit, bear in mind that WebSharper has active development, support, and has been used on real projects. Since we used it in larger projects, we had to take care with optimizing output code and working around some limitations and bugs in the F# reflection model, even rewriting F# metadata reader for our purpose. This means I can take dozens of closed issues from WebSharper tracker and re-discover them as Pit issues. I do not, for humanity would be ill served by such duplication of effort.
I think ClojureScript is better fit. It has same dynamic nature like JavaScript and it may use Google Closure Compiler for output optimisation. It it designed to run on JS VMs.
There are few differences from Clojure.

Categories

Resources