Nashorn: JavaScript je sjajan u Java 8

Nashorn, izgovara se "nass-horn", njemački je za "nosorog", i jedno je od životinjskih imena za njemački razarač tenkova korišten u Drugom svjetskom ratu. To je i ime zamjene - uvedene s Javom 8 - za stari, spor Rhino JavaScript motor. I Rhino i Nashorn su implementacije JavaScript jezika napisanog za pokretanje na Java virtualnom stroju ili JVM.

Obavezno rant: JavaScript možda ima Java kao dio imena, ali ta su dva jezika vrlo različita duhom i dizajnom, kao i implementacijom. Ipak, jedan od načina primjene JavaScript interpretera je kompajliranje JavaScript-a u Java bajt kodove, što su Rhino i Nashorn i zamišljeni.

Vjerojatno na JavaScript razmišljate u smislu skriptiranja web preglednika i uglavnom biste bili u pravu. Također se koristi za poslužitelje. Na primjer, Node.js koristi se za izgradnju brzih, laganih poslužitelja na temelju V8 JavaScript mehanizma iz Google Chromea. JavaScript motori u web preglednicima imaju pristup objektnom modelu HTML dokumenta (DOM) i mogu manipulirati HTML elementima putem DOM-a. S obzirom na to da različiti web preglednici imaju različite DOM-ove i JavaScript motore, okviri poput jQuery pokušavaju sakriti detalje o implementaciji od programera.

Nashorn i Rhino prije njega izričito ne podržavaju DOM preglednika. Primijenjene na JVM, obično se pozivaju za skriptiranje krajnjeg korisnika u Java aplikacijama. Nashorn i Rhino mogu se ugraditi u Java programe i koristiti kao ljuske naredbenog retka. Naravno, dodatna čarolija potrebna kada skriptirate Javu iz JavaScript-a je premošćivanje podataka i nepodudaranje vrsta između dva jezika.

Problemi s nosorogom

Razvoj nosoroga započeo je u Netscapeu 1997. za zlosretni projekt "Javagator", a objavljen je na Mozilla.org 1998. Tada je licenciran za Sun i druge. Iskreno, 1998. bi mogao biti i Jursko razdoblje, kako ide razvoj interneta - 16 godina kasnije, Rhino je jasno pokazao svoju starost. Prema Jimu Laskeyu iz Oraclea, glavnom programeru tvrtke Nashorn:

Siguran sam da je sve to istina, ali kao razuđeni programer i voditelj razvoja smatram zadnju rečenicu vrlo zabavnom. Napokon, glavni prepisi nikad nisu zabavni. Početi od nule uvijek je zabavno.

Golovi Nashorna

Laskey je svoje ciljeve za Nashorna opisao na sljedeći način:

  • Nashorn će se temeljiti na jezičnoj specifikaciji ECMAScript-262 Edition 5.1 i mora proći testove usklađenosti ECMAScript-262.
  • Nashorn će podržavati javax.scriptAPI (JSR 223).
  • Bit će pružena podrška za pozivanje Java koda iz JavaScripta i za Java za pozivanje JavaScript koda. To uključuje izravno mapiranje na JavaBeans.
  • Nashorn će definirati novi alat naredbenog retka jjsza procjenu JavaScript koda u skriptama "shebang", ovdje dokumente i uređivanje nizova.
  • Performanse i korištenje memorije Nashornovih aplikacija trebali bi biti znatno bolji od Rhino-a.
  • Nashorn neće izlagati nikakve dodatne sigurnosne rizike.
  • Isporučene knjižnice trebale bi ispravno funkcionirati pod lokalizacijom.
  • Poruke o pogreškama i dokumentacija internacionalizirat će se.

Laskey je također izričito ograničio opseg projekta s nekim "neciljevima":

  • Nashorn će podržavati samo ECMAScript-262 Edition 5.1. Ne podržava nijednu značajku izdanja 6 niti bilo koje nestandardne značajke koje pružaju druge implementacije JavaScript-a.
  • Nashorn neće sadržavati API dodatka za preglednik.
  • Nashorn neće sadržavati podršku za DOM / CSS ili bilo koje srodne knjižnice (poput jQuery, Prototype ili Dojo).
  • Nashorn neće uključivati ​​podršku za izravno ispravljanje pogrešaka.

Dakle, što znači biti zasnovan na ECMAScript-262 Edition 5.1? Ovdje se razlikuje što se Rhino temelji na starijem, manje sposobnom izdanju 3. javax.scriptAPI (JSR 223) služi za ponovno pozivanje JavaScripta s Jave.

Nedostatak podrške za otklanjanje pogrešaka u Nashornu korak je unatrag od Rhino-a, koji ima vlastiti JavaScript program za ispravljanje pogrešaka. Međutim, rješenja za ovaj namjerni propust pronaći ćete u najmanje dva popularna IDE-a.

Nashorn alati naredbenog retka: Instaliranje jjs-a i jrunscripta

Nakon što sam pročitao o Nashornovom alatu za naredbene retke, jjsbio sam nestrpljiv da isprobam ljusku na svom iMac-u, ali nakon instalacije Jave 8 nije bio dostupan bash ljusci. Ispostavilo se da dokumentacija i implementacija nisu bili potpuno sinkronizirani.

Znao sam da je instalacija bila uspješna:

 >java -version java version "1.8.0" Java(TM) SE Runtime Environment (build 1.8.0-b132) Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode) 

ali trčanje se jjsvratilo -bash: jjs: command not found. Malo provirivanja dovelo me do /usr/bin/direktorija:

 >which java /usr/bin/java 

Tamo sam pronašao nešto što se zove jrunscript, što se pokazalo varijantom jjskoja pokreće dodatnu skriptu za pokretanje. To bi me trebalo zadovoljiti, ali bio sam zbunjen zašto dokumentirani jjsalat nije instaliran u /usr/bin/ostatak Java 8 izvođenja. Malo me istraživanja navelo da pogledam JavaVirtualMachinesinstalaciju za Javu 8. Na Macu potražite jjsu /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/bin/ili /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/bin/.

Možete definirati alias za jjsu potonjem direktoriju i dodati ga u svoju konfiguraciju ljuske ako vam je potreban za skriptiranje na Macu ili Linuxu. Na računalu možete dodati ispravan jre/bin/direktorij u svoj PATH. U svom videu s pokretanja Jave 8, Jim Laskey predlaže kopiranje jjsu /usr/bin/direktorij, ali kad sam to učinio, otkrio sam da jjsJRE nije mogao ispravno pronaći u vrijeme izvođenja.

Pokretanje JavaScript skripti

Zašto dva alata naredbenog retka za pokretanje JavaScript skripti? Nisam potpuno jasan o čemu razmišlja razvojni tim, ali jjsima mogućnosti koje jrunscriptnemaju i jrunscriptima inicijalizacijsku datoteku. Ispod je nekoliko jednostavnih primjera jjsi jrunscriptupotrebe.

 $ jrunscript nashorn> alert("hello, "); script error: ReferenceError: "alert" is not defined in  at line number 1 

To ne radi jer alert()je funkcija preglednika / DOM-a. D'oh! Ipak bih se mogao zakleti da je to radilo u Rhinu.

 nashorn> print("Hello, "); Hello,  

To funkcionira jer je print () temeljna JavaScript funkcija.

 nashorn> var a = 1; nashorn> var b = "1"; nashorn> print (a+b); 11 nashorn> print(a+a); 2 nashorn> quit(); $ 

Drugim riječima, ovdje imamo osnovno okruženje REPL (read-execute-print-loop-command-line) za JavaScript. Ako ste iznenađeni odgovorom na a+b, razmislite o ovome:

 nashorn> print (typeof(a+b)); string 

To je šarmantna nuspojava labavog tipkanja i preopterećenja operatora "+" u JavaScript-u. To je ispravno ponašanje prema JavaScript specifikaciji, a ne greška.

Nashorn podržava „#” karakter kao vodeća markerom crta komentar, pa jjsi jrunscriptmože se koristiti u izvršnih „stvar” skripti napisanih u JavaScriptu. Na Macu ili Linuxu morat ćete označiti JavaScript datoteku kao izvršnu pomoću uslužnog programa chmod da biste je učinili dostupnom za pokretanje.

Naći ćete način skriptiranja jjskoji jrunscriptizgleda nedostaje. U načinu skriptiranja izrazi unutar back-tikova prosljeđuju se vanjskoj ljusci na ocjenu:

 $ jjs -scripting jjs> print ('ls'); Applications Applications (Parallels) Creative Cloud Files Desktop ... work jjs>

Način skriptiranja također omogućuje proširenje za "heredocs", koji su u osnovi višeredni nizovi u formatu koji je poznat programerima Perl i Ruby.

By the way, the arrow keys on the Mac keyboard don't work properly for line editing in the jjs shell. But there is a hack for that: You can brew install rlwrap and use that as part of your alias for jjs in your .bashrc or .zshrc file.

Calling JavaScript from Java

To call Nashorn JavaScript from a Java 8 program, you basically need to make a new ScriptEngineManager instance and use that ScriptEngineManager to load the Nashorn script engine by name. (See this Stack Overflow question for a pithy summary of loading and debugging Nashorn.)

Finally, you can pass the Nashorn engine a file or a string to evaluate:

 import javax.script.Invocable; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; ... try { ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine engine = factory.getEngineByName("nashorn"); engine.eval("load(\"" + "src" + "/" + "javascript_sample" + "/" + "test1.js" + "\");"); } catch (Exception ex) { //... } ... try { ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine engine = factory.getEngineByName("nashorn"); engine.eval("function hi(){\nvar a = 'PROSPER'.toLowerCase(); \nmiddle(); \nprint('Live long and' + a)}\n function middle(){\n var b = 1; for(var i=0, max = 5; i
    

Note that scripts can always generate ScriptException errors, so you need to catch them.

Calling Java from JavaScript

Calling Java from Nashorn is about as easy as it can be, since the Java 8 class libraries are built into Nashorn:

 print(java.lang.System.currentTimeMillis()); var file = new java.io.File("sample.js"); print(file.getAbsolutePath()); print(file.absolutePath); 

Note that Nashorn does not import the java package by default, because references to String or Object conflict with the corresponding types in JavaScript. Hence, a Java string is java.lang.String, not String.

Nashorn and JavaFX

If you invoke jjs with the -fx switch, it will allow you to use visual JavaFX classes in your Nashorn applications. For instance, the following example from the Oracle documentation displays a JavaFX button:

 var Button = javafx.scene.control.Button; var StackPane = javafx.scene.layout.StackPane; var Scene = javafx.scene.Scene; function start(primaryStage) { primaryStage.title = "Hello World!"; var button = new Button(); button.text = "Say 'Hello World'"; button.onAction = function() print("Hello World!"); var root = new StackPane(); root.children.add(button); primaryStage.scene = new Scene(root, 300, 250); primaryStage.show(); } 

Debugging Nashorn

I mentioned earlier that Nashorn doesn't include a debugger of its own. Fortunately, both NetBeans 8 and IntelliJ IDEA 13.1 support debugging Nashorn JavaScript. The Stack Overflow question I mentioned earlier includes a useful NetBeans 8 project that you can use as a sample. You'll find that simply using the debug item from the pop-up menu on JavaScript files will allow you to debug the Nashorn code.

In IntelliJ IDEA 13, you can set breakpoints in the Java and Nashorn JavaScript files using the same shortcut key (Com/Ctrl-F8). When you hit a JavaScript breakpoint, you get all the usual debugging information.

Nashorn was designed to be a better, faster replacement for the old Rhino engine, and by most measures it succeeds. It has some minor warts that I hope will be corrected in future updates, but for now there are reasonable hacks to let you use Nashorn effectively in your projects.