Statische typeanalyse in JavaScript. Laten we de Flow-analyzer van Facebook proberen. JavaScript-beveiliging of hoe u veilige code schrijft in JS Analytics en code-optimalisatietools

Niet elke regel van mijn code is de eerste keer perfect. Nou ja, in sommige gevallen... Soms... Oké, bijna nooit. De waarheid is dat ik aanzienlijk meer tijd besteed aan het corrigeren van mijn eigen stomme fouten dan ik zou willen. Dit is de reden waarom ik statische analysatoren gebruik in bijna elk JavaScript-bestand dat ik schrijf.

Statische analysers kijken naar uw code en vinden er fouten in voordat u deze uitvoert. Ze voeren eenvoudige controles uit, zoals het controleren op handhavingssyntaxis (zoals of er tabs zijn in plaats van spaties) en meer globale controles, zoals het controleren of functies niet te complex zijn. Statische analysatoren zoeken ook naar fouten die tijdens het testen niet kunnen worden gevonden, bijvoorbeeld == in plaats van ===.

Bij grote projecten en als je in grote teams werkt, kun je wel wat hulp gebruiken bij het vinden van die ‘eenvoudige’ bugs die eigenlijk niet zo eenvoudig blijken te zijn als ze lijken.

JSLint, JSHint en Closure-compiler

Er zijn drie hoofdopties voor statische analysers voor JavaScript: JSLint, JSHint en Closure Compiler.

JSLint was de eerste statische parser voor JavaScript. U kunt het op de officiële website uitvoeren of een van de add-ons gebruiken die in lokale bestanden kunnen worden uitgevoerd. JSLint vindt veel belangrijke fouten, maar het is erg lastig. Hier is een duidelijk voorbeeld:

Var s = "mijntekenreeks"; voor (var i = 0; i< s.length; i++) { console.log(s.charAt(i)); }

JSLint toont twee fouten in deze code:

Onverwachte "++". Verplaats "var"-declaraties naar de bovenkant van de functie.

Het eerste probleem is het definiëren van de variabele i in de lusvoorwaarden. JSLint accepteert ook niet de ++-operator aan het einde van een lusdefinitie. Hij wil dat de code er zo uitziet:

Var s = "mijntekenreeks"; var ik; voor (i = 0; ik< s.length; i = i + 1) { console.log(s.charAt(i)); }

Ik waardeer de makers van JSLint, maar naar mijn mening is dit overdreven. Ook voor Anton Kovalev bleek het zwaar te zijn, dus richtte hij JSHint op.

JSHint werkt op dezelfde manier als JSLint, maar wordt als aanvulling op Node.js geschreven en is daardoor flexibeler. JSHint bevat een groot aantal opties, waardoor u aangepaste controles kunt uitvoeren door uw eigen rapportgenerator te schrijven.
U kunt JSHint vanaf de website uitvoeren, maar in de meeste gevallen is het beter om JSHint te installeren als een lokaal opdrachtregelprogramma met behulp van Node.js. Zodra JSHint is geïnstalleerd, kunt u het op uw bestanden uitvoeren met een opdracht als deze:

Jsint-test.js

JSHint bevat ook plug-ins voor populaire teksteditors, zodat u deze kunt uitvoeren terwijl u code schrijft.

SLUITING COMPILER

Google's Closure Compiler is een heel ander type programma. Zoals de naam al doet vermoeden, is het niet alleen een verificatieprogramma, maar ook een compiler. Het is geschreven in Java en is gebaseerd op Mozilla's Rhino-parser. Closure Compiler bevat een eenvoudige modus voor het uitvoeren van basiscodecontroles, en complexere modi die extra controle en handhaving van specifieke weergavedefinities mogelijk maken.

Closure Compiler rapporteert fouten in JavaScript-code, maar produceert ook verkleinde versies van JavaScript. De compiler verwijdert witruimte, commentaar en ongebruikte variabelen en vereenvoudigt lange expressies, waardoor het script zo compact mogelijk wordt.

Google heeft een zeer eenvoudige versie van de compiler online beschikbaar gemaakt, maar u zult waarschijnlijk Closure Compiler willen downloaden en lokaal uitvoeren.

Closure Compiler voert, na het controleren van de code, een lijst met bestanden uit in één verkleind bestand. U kunt het dus uitvoeren door het bestand compiler.jar te downloaden.

Java -jar compiler.jar --js_output_file compress.js --js test1.js --js test2.js

Het juiste verificatieprogramma kiezen

In mijn projecten combineer ik Closure Compiler en JSHint. Closure Compiler voert minificatie en basiscontrole uit, terwijl JSHint complexere codeanalyse uitvoert. Deze twee programma's werken goed samen en bestrijken elk gebieden die de ander niet kan. Bovendien kan ik de JSHint-extensiemogelijkheden gebruiken om aangepaste checkers te schrijven. Eén generiek programma dat ik heb geschreven, controleert op bepaalde functies die ik niet nodig heb, zoals het aanroepen van functies die niet in mijn project zouden moeten voorkomen.

Nu we een paar programma's hebben bekeken om te controleren, laten we eens kijken naar slechte code. Elk van deze zes voorbeelden vertegenwoordigt code die niet geschreven zou moeten worden en situaties waarin code-reviewers u kunnen redden.

In dit artikel wordt voor de meeste voorbeelden JSHint gebruikt, maar Closure Compiler geeft doorgaans vergelijkbare waarschuwingen.

== of ===?

JavaScript is een dynamisch getypeerde taal. U hoeft geen typen te definiëren wanneer u code schrijft, maar ze bestaan ​​al bij het opstarten.

JavaScript biedt twee vergelijkingsoperatoren om deze dynamische typen te manipuleren: == en ===. Laten we dit eens bekijken met een voorbeeld.

Varn = 123; var s = "123"; if (n == s) ( alert("Variabelen zijn gelijk"); ) if (n === s) ( alert("Variabelen zijn identiek"); )

Vergelijkingsoperator == zijn overblijfselen van de C-taal, waarin JavaScript zijn wortels heeft. Het gebruik ervan is bijna altijd een vergissing: waarden los van typen vergelijken is zelden wat de ontwikkelaar daadwerkelijk wil doen. In feite is het getal 'honderddrieëntwintig' anders dan de regel 'één twee drie'. Deze uitspraken zijn gemakkelijk verkeerd te spellen en nog gemakkelijker verkeerd te lezen. Test deze code met JSHint en je krijgt het volgende:

Test.js: regel 9, kolom 12, verwachtte "===" en zag in plaats daarvan "==".

Ongedefinieerde variabelen en late definities

Laten we beginnen met wat eenvoudige code:

Functietest() ( var myVar = "Hallo wereld"; console.log(myvar); )

Zie je een bug? Deze fout maak ik elke keer. Voer deze code uit en je krijgt een foutmelding:

ReferenceError: myvar is niet gedefinieerd

Laten we het probleem wat ingewikkelder maken:

Functietest() ( myVar = "Hallo wereld"; console.log(myVar); )

Voer deze code uit en je krijgt het volgende:

Hallo wereld

Dit tweede voorbeeld werkt, maar heeft enkele zeer onverwachte bijwerkingen. De regels voor het definiëren van JavaScript-variabelen en -bereik zijn op zijn best verwarrend. In het eerste geval rapporteert JSHint het volgende:

Test.js: regel 3, kolom 17, "myvar" is niet gedefinieerd.

In het tweede geval zal hij dit melden:

Test.js: regel 2, kolom 5, "myVar" is niet gedefinieerd. test.js: regel 3, kolom 17, "myVar" is niet gedefinieerd.

Het eerste voorbeeld helpt u een runtimefout te voorkomen. U hoeft uw applicatie niet te testen - JSHint zal de bug voor u vinden. Het tweede voorbeeld is nog erger, omdat je als resultaat van het testen geen bug zult vinden.

Het probleem in het tweede voorbeeld is verraderlijk subtiel en complex. De variabele myVar is nu uit zijn bereik verdwenen en verplaatst naar het globale bereik. Dit betekent dat het zal bestaan ​​en de waarde Hallo, Wereld zal hebben, zelfs nadat de testfunctie is uitgevoerd. Dit wordt mondiale omvangvervuiling genoemd.

De myVar-variabele bestaat voor elke andere functie die na de testfunctie wordt uitgevoerd. Voer de volgende code uit nadat u de testfunctie hebt uitgevoerd:

Console.log("mijnVar: " + mijnVar);

Je ontvangt nog steeds Hello, World. De myVar-variabele blijft als een sjabloon rond uw hele code hangen, wat leidt tot complexe bugs waar u de hele nacht vóór de release naar op zoek zult zijn, allemaal omdat u bent vergeten var op te nemen.

En een docent Netologie schreef een reeks artikelen over EcmaScript6 voor de blog. In het eerste deel zullen we aan de hand van voorbeelden kijken naar dynamische code-analyse in EcmaScript met behulp van Iroh.js.

Statische en dynamische codeanalyse

Codeanalysetools zijn een handig hulpmiddel waarmee u fouten en eigenaardigheden in uw code kunt detecteren en identificeren. Codeanalyse kan statisch of dynamisch zijn. In het eerste geval wordt de broncode geparseerd en geanalyseerd zonder deze uit te voeren; in het tweede geval vindt de uitvoering plaats in een gecontroleerde sandbox-omgeving, die tijdens de uitvoering meta-informatie verschaft over de elementen van de applicatie.

Conclusies

Iroh.js is een krachtige en functionele tool voor dynamische codeanalyse in EcmaScript. Deze tool kan zowel worden gebruikt voor codeanalyse, inclusief het bouwen van een oproepgrafiek, het afleiden van werkelijke typen en waarden in variabelen en objecten, als voor on-the-fly codewijziging, inclusief op gebeurtenissen gebaseerde codecorrecties.

Dynamische analyse is een nogal complexe methode, maar voor EcmaScript is dit, gezien het duck-typeren, de aanwezigheid van hostobjecten en native functies waarmee je het gedrag van de code direct kunt wijzigen, de enige manier om code tijdens het proces te analyseren en te debuggen. uitvoering. Iroh.js kan ook code gebruiken om functionele tests te maken zonder deze eerst te hoeven wijzigen om waarden te exporteren.

Het is een modulaire packager die een afhankelijkheidsgrafiek maakt met alle modules voor een JavaScript-applicatie. Webpack verpakt modules in een of meer kleine pakketten die door de browser kunnen worden geladen. Bovendien kan Webpack worden gebruikt als taakrunner, omdat het de afhankelijkheden tussen modules parseert en assets genereert. Meer informatie over het gebruik van Webpack in uw projecten vindt u in onze.

  • Grunt is een taskrunner die is ontworpen om repetitieve en tijdrovende taken te automatiseren. Er zijn een groot aantal plug-ins (meer dan 6000) in het software-ecosysteem.
  • Gulp is niet zomaar een taakbeheerder, maar een tool met een interessante insteek: het definieert taken in JavaScript als functies, GUl automatiseert ook pijnlijke taken, biedt een groot software-ecosysteem (meer dan 2700 plug-ins) en het zorgt voor betere transparantie en controle over de proces.
  • Met Browserify kunnen softwareontwikkelaars modules in NodeJS-stijl in browsers gebruiken. U definieert de afhankelijkheden en Browserify verpakt het allemaal in een netjes JS-bestand.
  • Brunch.io is een tool waarvan de belangrijkste ideeën snelheid en eenvoud zijn. Het wordt geleverd met een eenvoudige configuratie en gedetailleerde documentatie, zodat u snel aan de slag kunt. Brunch genereert automatisch een kaart van JS-bestanden samen met CSS-stijlbladen, waardoor foutopsporing aan de clientzijde eenvoudiger wordt.
  • Yeoman is een universele tool die met vrijwel elke programmeertaal kan worden gebruikt (JavaScript, Python, C#, Java en andere). Dit basiscodegeneratiesysteem met een rijk software-ecosysteem (meer dan 6.200 plug-ins) wordt gebruikt voor het ontwikkelen van webapplicaties. Dankzij Yeoman kunt u snel nieuwe projecten creëren zonder het onderhoud en de verbetering van bestaande projecten te vergeten.
  • IDE's en code-editors

    • Swagger is een set regels en hulpmiddelen voor het beschrijven van API's. De tool is een taalonafhankelijk hulpprogramma. Dit betekent dat Swagger duidelijke documentatie creëert die leesbaar is voor zowel mens als machine, waardoor u API-afhankelijke processen kunt automatiseren.
    • JSDoc is een set tools die automatisch tekstdocumentatie van meerdere pagina's (HTML, JSON, XML, enz.) genereren op basis van opmerkingen uit de JavaScript-broncode. Deze applicatie kan handig zijn voor het beheren van grootschalige projecten.
    • jGrouseDoc (jGD) is een flexibele, open-sourcetool waarmee ontwikkelaars API's kunnen genereren op basis van opmerkingen uit JavaScript-broncode. jGD documenteert niet alleen variabelen en functies, maar ook naamruimten, interfaces, pakketten en enkele andere elementen.
    • YUIDoc is een applicatie geschreven in NodeJS. Het gebruikt een syntaxis die vergelijkbaar is met die van Javadoc en Doxygen. De tool beschikt ook over realtime preview-ondersteuning, geavanceerde taalondersteuning en geavanceerde markup.
    • Docco is een gratis documentatietool geschreven in het literaire CoffeeScript. Er wordt een HTML-document gemaakt waarin uw opmerkingen worden weergegeven, afgewisseld met code. Opgemerkt moet worden dat de tool niet alleen JavaScript ondersteunt, maar ook andere talen. Bijvoorbeeld Python, Ruby, Clojure en anderen.

    Hulpmiddelen testen

    Testtools voor JavaScript zijn ontworpen om fouten tijdens de ontwikkeling op te sporen en zo gebruikersfouten in de toekomst te voorkomen. Naarmate de complexiteit van gebruikersapplicaties toeneemt, verbeteren geautomatiseerde tests niet alleen de applicatieprestaties, maar helpen ze bedrijven ook budget te besparen.

    • Jasmine is een BDD-framework (Behavior-driven Development) dat wordt gebruikt voor het testen van JS-code. Het heeft geen externe afhankelijkheden en vereist niet dat de DOM wordt uitgevoerd. Jasmine heeft een duidelijke en begrijpelijke syntaxis die het testen sneller en eenvoudiger maakt. Het framework kan ook worden gebruikt om Python- en Ruby-code te testen.
    • Mocha is een functioneel testframework dat Node.js in de browser draait. Het voert tests sequentieel uit om flexibele en nauwkeurige rapportage te bieden, waardoor asynchrone tests leuk en gemakkelijk worden. Mokka wordt vaak gebruikt in combinatie met Chai om testresultaten te verifiëren.
    • PhantomJS wordt vaak gebruikt voor front-end tests en unit tests. Aangezien dit een soort headless WebKit is, werken scripts veel sneller. Het bevat ook ingebouwde ondersteuning voor verschillende webstandaarden. Bijvoorbeeld JSON-, Canvas-, DOM-verwerking, SVG- en CSS-selectors.
    • Protractor is een end-to-end testframework geschreven in Node.js voor het testen van AngularJS en Angular-applicaties. Het is bovenop WebDriverJS gebouwd en test applicaties zoals een eindgebruiker met behulp van aangepaste stuurprogramma's en ingebouwde gebeurtenissen.

    Hulpmiddelen voor foutopsporing

    Het debuggen van code is een nogal arbeidsintensief en tijdrovend proces voor JavaScript-ontwikkelaars. Tools voor het opsporen van fouten in code zijn vooral handig als u met duizenden regels code werkt. Veel van de foutopsporingstools leveren redelijk nauwkeurige resultaten op.

    • JavaScript Debugger is een tool van het Mozilla Developer Network (MDN) die kan worden gebruikt als een zelfstandige webapplicatie om code in verschillende browsers te debuggen. Firefox biedt lokale en externe functionaliteit, evenals de mogelijkheid om code op een Android-apparaat te debuggen met behulp van Firefox voor Android.
    • Chrome Dev Tools is een set tools die verschillende hulpprogramma's bevat voor het debuggen van JavaScript-code, het bewerken van CSS en het testen van de prestaties van applicaties.
    • ng-inspector is een browserextensie die is ontworpen om ontwikkelaars te helpen bij het schrijven, begrijpen en debuggen van AngularJS-applicaties. Het hulpprogramma wordt geleverd met realtime updates, DOM-accentuering, directe toegang tot regio's, modellen en andere applicatie-elementen.
    • Augury is een extensie voor het debuggen van de Google Chrome-browser en Angular 2-applicaties. Hiermee kunnen ontwikkelaars van Angular 2-applicaties de applicatiestructuur en prestatiekenmerken rechtstreeks analyseren, en is het ook mogelijk om wijzigingen te detecteren.

    Beveiligingshulpmiddelen

    • Snyk is een commerciële tool voor het detecteren, repareren en voorkomen van bekende kwetsbaarheden in JavaScript-, Java- en Ruby-applicaties. De dienst beschikt over een eigen kwetsbaarheidsdatabase en haalt gegevens van NSP en NIST NVD. Met de patches en updates die het bedrijf biedt, kunnen ontwikkelaars beveiligingsrisico’s voorkomen.
    • Het Node Security Project biedt handige tools voor het scannen van afhankelijkheid en het detecteren van kwetsbaarheden. NSP maakt gebruik van een eigen database die is opgebouwd uit het scannen van npm-modules, evenals gegevens uit algemene databases zoals NIST NVD (National Vulnerability Database). Daarnaast biedt NSP integratie met GitHub Pull Request en CI-software. Er zijn ook realtime controles, waarschuwingen en aanbevelingen voor het elimineren van kwetsbaarheden in Node.js-applicaties.
    • RetireJS is een open source afhankelijkheidscontrole. Bevat verschillende componenten zoals een opdrachtregelscanner, Grunt-plug-in, Firefox- en Chrome-extensies, Burp-plug-ins en OWASP ZAP. Retirejs verzamelt informatie over kwetsbaarheden van NIST NVD en andere bronnen, zoals issue trackers, blogs en mailinglijsten.
    • Gemnasium is een commerciële tool met een gratis proefperiode. Het ondersteunt een verscheidenheid aan technologieën en pakketten, waaronder Ruby, PHP, Bower (JavaScript), Python en npm (JavaScript). De Gemnasium-beveiligingstool wordt geleverd met handige functies zoals automatische updates, realtime waarschuwingen, beveiligingsmeldingen en Slack-integratie.
    • OSSIndex ondersteunt verschillende ecosystemen (Java, JavaScript en .NET/C#) en vele platforms zoals NuGet, npm, Bower, Chocolatey, Maven, Composer, Drupal en MSI. Het verzamelt kwetsbaarheidsinformatie uit de Nationale Vulnerability Database (NVD) en feedback. Het verwerkt ook informatie van communityleden.

    Analyse- en code-optimalisatietools

    Om de kwaliteit van code te controleren, wenden we ons meestal tot functioneel testen en unit-testen. Er is echter een andere aanpak waarmee ontwikkelaars de kwaliteit van de code en de naleving ervan met coderingsstandaarden kunnen controleren, namelijk statische code-analyse.

    Moderne software integreert nu tools om statische code tijdens de ontwikkeling te analyseren om ervoor te zorgen dat code van lage kwaliteit niet in productie komt.

    • JSLint is een webanalysetool waarmee u de kwaliteit van JavaScript-code kunt controleren. Zodra het een probleem bij de bron detecteert, retourneert het een bericht waarin het probleem en de geschatte locatie in de code worden beschreven. JSLint is in staat bepaalde stijlconventies te analyseren en syntaxisfouten en structurele problemen bloot te leggen.
    • JSHint is een flexibele, door de gemeenschap aangestuurde tool voor het detecteren van bugs en potentiële problemen in uw JS-code, en is ook een afsplitsing van JSLint. Het belangrijkste doel van deze tool voor het analyseren van statische code is om JavaScript-ontwikkelaars te helpen bij het werken aan complexe programma's. Het is in staat syntaxisfouten, impliciete datatypeconversie of ontbrekende variabelen te detecteren. Het kan echter niet de snelheid of correctheid van uw applicatie bepalen, noch geheugenproblemen in uw applicatie vaststellen. JSHint is een vork van JSLint.
    • ESLint is een open source linter voor JSX- en JavaScript-webapplicaties. Het helpt u twijfelachtige patronen te ontdekken of code te vinden die niet aan specifieke stijlen voldoet. Hierdoor kunnen ontwikkelaars fouten in JS-code detecteren zonder deze uit te voeren, waardoor tijd wordt bespaard. De tool is geschreven in Node.js en biedt een snelle runtime en naadloze installatie via npm.
    • Flow is een statische codecontroller voor JavaScript ontwikkeld door Facebook. Het maakt gebruik van annotaties van het statische type om code op fouten te controleren. Typen zijn parameters die door ontwikkelaars zijn ingesteld, en Flow controleert uw software op naleving ervan.

    Versiebeheerhulpmiddelen

    • Git is de afgelopen jaren uitgegroeid tot een veelgebruikt versiebeheersysteem voor zowel kleine als grote projecten. Dit gratis hulpprogramma biedt uitstekende snelheid en efficiëntie. De populariteit is te danken aan het gedistribueerde systeem en de verschillende soorten besturingselementen, evenals aan een verzamelgebied waar versies kunnen worden bekeken en geformatteerd vlak voordat de commit is voltooid.
    • De Subversion- of SVN-tool is enorm populair geworden en wordt nog steeds veel gebruikt in open source-projecten en platforms zoals Python Apache of Ruby. Deze CVS wordt geleverd met vele functies waarmee u verschillende bewerkingen (hernoemen, kopiëren, verwijderen, enz.), samenvoegingen, bestandsvergrendeling en nog veel meer kunt beheren.

    Hulpmiddelen voor pakket- en afhankelijkheidsbeheer

    De lijst met de beste tools voor JavaScript-ontwikkeling kan eindeloos doorgaan. In dit artikel zag je alleen populaire en betrouwbare tools die als basis dienen voor kwaliteitsproducten.

    Niet elke regel van mijn code is de eerste keer perfect. Nou ja, in sommige gevallen... Soms... Oké, bijna nooit. De waarheid is dat ik aanzienlijk meer tijd besteed aan het corrigeren van mijn eigen stomme fouten dan ik zou willen. Dit is de reden waarom ik statische analysatoren gebruik in bijna elk JavaScript-bestand dat ik schrijf.

    Statische analysers kijken naar uw code en vinden er fouten in voordat u deze uitvoert. Ze voeren eenvoudige controles uit, zoals het controleren op handhavingssyntaxis (zoals of er tabs zijn in plaats van spaties) en meer globale controles, zoals het controleren of functies niet te complex zijn. Statische analysatoren zoeken ook naar fouten die tijdens het testen niet kunnen worden gevonden, bijvoorbeeld == in plaats van ===.


    Bij grote projecten en als je in grote teams werkt, kun je wel wat hulp gebruiken bij het vinden van die ‘eenvoudige’ bugs die eigenlijk niet zo eenvoudig blijken te zijn als ze lijken.


    JSLint, JSHint en Closure-compiler


    Er zijn drie hoofdopties voor statische analysers voor JavaScript: JSLint, JSHint en Closure Compiler.



    JSLint was de eerste statische parser voor JavaScript. U kunt het op de officiële website uitvoeren of een van de add-ons gebruiken die in lokale bestanden kunnen worden uitgevoerd. JSLint vindt veel belangrijke fouten, maar het is erg lastig. Hier is een duidelijk voorbeeld:



    var s = "mijntekenreeks";
    voor (var i = 0; i< s.length; i++) {
    console.log(s.charAt(i));
    }

    JSLint toont twee fouten in deze code:



    Onverwachte "++".
    Verplaats "var"-declaraties naar de bovenkant van de functie.

    Het eerste probleem is het definiëren van de variabele i in de lusvoorwaarden. JSLint accepteert ook niet de ++-operator aan het einde van een lusdefinitie. Hij wil dat de code er zo uitziet:



    var s = "mijntekenreeks";
    var ik;
    voor (i = 0; ik< s.length; i = i + 1) {
    console.log(s.charAt(i));
    }

    Ik waardeer de makers van JSLint, maar naar mijn mening is dit overdreven. Ook voor Anton Kovalev bleek het zwaar te zijn, dus richtte hij JSHint op.



    JSHint werkt op dezelfde manier als JSLint, maar wordt als aanvulling op Node.js geschreven en is daardoor flexibeler. JSHint bevat een groot aantal opties, waardoor u aangepaste controles kunt uitvoeren door uw eigen rapportgenerator te schrijven.

    U kunt JSHint vanaf de website uitvoeren, maar in de meeste gevallen is het beter om JSHint te installeren als een lokaal opdrachtregelprogramma met behulp van Node.js. Zodra JSHint is geïnstalleerd, kunt u het op uw bestanden uitvoeren met een opdracht als deze:



    jsint-test.js

    JSHint bevat ook plug-ins voor populaire teksteditors, zodat u deze kunt uitvoeren terwijl u code schrijft.


    SLUITING COMPILER


    Google's Closure Compiler is een heel ander type programma. Zoals de naam al doet vermoeden, is het niet alleen een verificatieprogramma, maar ook een compiler. Het is geschreven in Java en is gebaseerd op Mozilla's Rhino-parser. Closure Compiler bevat een eenvoudige modus voor het uitvoeren van basiscodecontroles, en complexere modi die extra controle en handhaving van specifieke weergavedefinities mogelijk maken.


    Closure Compiler rapporteert fouten in JavaScript-code, maar produceert ook verkleinde versies van JavaScript. De compiler verwijdert witruimte, commentaar en ongebruikte variabelen en vereenvoudigt lange expressies, waardoor het script zo compact mogelijk wordt.


    Google heeft een zeer eenvoudige versie van de compiler online beschikbaar gemaakt, maar u zult waarschijnlijk Closure Compiler willen downloaden en lokaal uitvoeren.


    Closure Compiler voert, na het controleren van de code, een lijst met bestanden uit in één verkleind bestand. U kunt het dus uitvoeren door het bestand compiler.jar te downloaden.



    java -jar compiler.jar --js_output_file compress.js --js test1.js --js test2.js

    Het juiste verificatieprogramma kiezen


    In mijn projecten combineer ik Closure Compiler en JSHint. Closure Compiler voert minificatie en basiscontrole uit, terwijl JSHint complexere codeanalyse uitvoert. Deze twee programma's werken goed samen en bestrijken elk gebieden die de ander niet kan. Bovendien kan ik de JSHint-extensiemogelijkheden gebruiken om aangepaste checkers te schrijven. Eén generiek programma dat ik heb geschreven, controleert op bepaalde functies die ik niet nodig heb, zoals het aanroepen van functies die niet in mijn project zouden moeten voorkomen.


    Nu we een paar programma's hebben bekeken om te controleren, laten we eens kijken naar slechte code. Elk van deze zes voorbeelden vertegenwoordigt code die niet geschreven zou moeten worden en situaties waarin code-reviewers u kunnen redden.


    In dit artikel wordt voor de meeste voorbeelden JSHint gebruikt, maar Closure Compiler geeft doorgaans vergelijkbare waarschuwingen.


    == of ===?


    JavaScript is een dynamisch getypeerde taal. U hoeft geen typen te definiëren wanneer u code schrijft, maar ze bestaan ​​al bij het opstarten.


    JavaScript biedt twee vergelijkingsoperatoren om deze dynamische typen te manipuleren: == en ===. Laten we dit eens bekijken met een voorbeeld.



    var n = 123;
    var s = "123";

    als (n == s) (
    alert("Variabelen zijn gelijk");
    }

    als (n === s) (
    alert("Variabelen zijn identiek");
    }

    Vergelijkingsoperator == is een overblijfsel van de C-taal, waarin JavaScript zijn wortels heeft. Het gebruik ervan is bijna altijd een vergissing: waarden los van typen vergelijken is zelden wat de ontwikkelaar daadwerkelijk wil doen. In feite is het getal 'honderddrieëntwintig' anders dan de regel 'één twee drie'. Deze uitspraken zijn gemakkelijk verkeerd te spellen en nog gemakkelijker verkeerd te lezen. Test deze code met JSHint en je krijgt het volgende:

    test.js: regel 9, kolom 12, verwachtte "===" en zag in plaats daarvan "==".

    Ongedefinieerde variabelen en late definities


    Laten we beginnen met wat eenvoudige code:



    functietest() (
    var myVar = "Hallo, wereld";
    console.log(mijnvar);
    }

    Zie je een bug? Deze fout maak ik elke keer. Voer deze code uit en je krijgt een foutmelding:



    ReferenceError: myvar is niet gedefinieerd

    Laten we het probleem wat ingewikkelder maken:



    functietest() (
    myVar = "Hallo, Wereld";
    console.log(mijnVar);
    }

    Voer deze code uit en je krijgt het volgende:



    Hallo wereld

    Dit tweede voorbeeld werkt, maar heeft enkele zeer onverwachte bijwerkingen. De regels voor het definiëren van JavaScript-variabelen en -bereik zijn op zijn best verwarrend. In het eerste geval rapporteert JSHint het volgende:

    test.js: regel 3, kolom 17, "myvar" is niet gedefinieerd.

    In het tweede geval zal hij dit melden:



    test.js: regel 2, kolom 5, "myVar" is niet gedefinieerd.
    test.js: regel 3, kolom 17, "myVar" is niet gedefinieerd.

    Het eerste voorbeeld helpt u een runtimefout te voorkomen. U hoeft uw applicatie niet te testen - JSHint zal de bug voor u vinden. Het tweede voorbeeld is nog erger, omdat je als resultaat van het testen geen bug zult vinden.


    Het probleem in het tweede voorbeeld is verraderlijk subtiel en complex. De variabele myVar is nu uit zijn bereik verdwenen en verplaatst naar het globale bereik. Dit betekent dat het zal bestaan ​​en de waarde Hallo, Wereld zal hebben, zelfs nadat de testfunctie is uitgevoerd. Dit wordt mondiale omvangvervuiling genoemd.


    De myVar-variabele bestaat voor elke andere functie die na de testfunctie wordt uitgevoerd. Voer de volgende code uit nadat u de testfunctie hebt uitgevoerd:



    console.log("mijnVar: " + mijnVar);

    Je ontvangt nog steeds Hello, World. De myVar-variabele blijft als een sjabloon rond uw hele code hangen, wat leidt tot complexe bugs waar u de hele nacht vóór de release naar op zoek zult zijn, allemaal omdat u bent vergeten var op te nemen.


    Dit bericht is via de Full-Text RSS-service doorgegeven. Als dit uw inhoud is en u leest deze op de site van iemand anders, lees dan de FAQ op http://ift.tt/jcXqJW.


    Het ontwikkelen van veilige applicaties in JavaScript is een behoorlijk complexe onderneming. Maar prima te doen. In het artikel van vandaag zullen we kijken naar de kenmerken van JavaScript die beveiligingsproblemen veroorzaken en praten over manieren om deze te vermijden.

    Waarom is het moeilijk om veilige code in JS te schrijven?

    Hier zijn dus 5 redenen waarom het moeilijk is om veilige code in JS te schrijven

    De compiler helpt niet

    JavaScript is een geïnterpreteerde taal. Dit betekent dat de compiler niet de hele tijd ergens over zal klagen, weigeren te werken en u ertoe aanzet fouten te herstellen en de code te optimaliseren.

    De dynamische essentie van JavaScript

    JavaScript is dynamisch, zwak getypeerd en asynchroon. En dit zijn allemaal tekenen dat het gemakkelijk is om in de problemen te komen.

    1. Taalhulpmiddelen zoals eval en de toevoeging van code van derden via script src zorgen ervoor dat u regels direct tijdens runtime kunt uitvoeren. Als gevolg hiervan is het moeilijk om “statische garanties” te geven dat de code zich op een bepaalde manier zal gedragen. Dit maakt dynamische analyse ook moeilijk (zie wetenschappelijk werk).

    Eval gebruiken

    2. Zwak typen Dit maakt het lastig om gevestigde statische analysetechnieken toe te passen, althans vergeleken met statisch getypeerde talen (zoals Java).

    3. Asynchrone terugbelgesprekken, oproepen die JavaScript toestaat via mechanismen als setTimeout en XMLHttpRequest (dezelfde beroemde AJAX), volgens de statistieken, verbergen de meest verraderlijke fouten.

    Ingewikkelde JS-functies

    Wat is er door de jaren heen niet in JavaScript gebracht! Het heeft met name prototypes, eersteklas functies en sluitingen. Ze maken de taal nog dynamischer en het schrijven van veilige code moeilijker.

    1. Prototypen. Hun betekenis is dat programma's zijn geschreven in de geest van een objectgeoriënteerde benadering, maar zonder het gebruik van klassen. Met deze aanpak erven objecten de eigenschappen die ze nodig hebben rechtstreeks van andere objecten (prototypes). Bovendien kunnen prototypes in JS direct tijdens runtime opnieuw worden gedefinieerd. En als deze herdefinitie plaatsvindt, verspreidt het effect zich onmiddellijk naar alle objecten die de eigenschappen van het overschreven prototype erven.

    Hoe prototypes worden verwerkt

    Om eerlijk te zijn moet gezegd worden dat klassen ook aanwezig zijn in de nieuwe ECMAScript-specificaties.

    2. Eersteklas functies. JS heeft een zeer flexibel model van objecten en functies. Objecteigenschappen en hun waarden kunnen direct tijdens runtime worden aangemaakt, gewijzigd of verwijderd, en alles is toegankelijk via eersteklas functies.

    3. Sluitingen. Als je een functie binnen een andere functie declareert, heeft de eerste toegang tot de variabelen en argumenten van de laatste. Bovendien blijven deze variabelen bestaan ​​en blijven ze beschikbaar voor de interne functie - zelfs nadat de externe functie waarin deze variabelen zijn gedefinieerd is voltooid.

    Omdat JavaScript zo flexibel en dynamisch is (zie punten 1 en 3), is het bepalen van de verzameling van alle beschikbare eigenschappen van een object tijdens statische analyse een lastige taak. Webontwikkelaars maken echter overal gebruik van de dynamische kenmerken van de taal, en dienovereenkomstig kunnen ze niet worden verwaarloosd bij het analyseren van code. Wat is anders de garantie voor veiligheid?

    Nauwe interactie tussen JavaScript en DOM

    Dit is nodig om een ​​“naadloze” update van de webpagina te garanderen, direct tijdens runtime. De DOM, zoals wij die kennen, is een standaard, platform- en taalneutraal objectmodel voor het weergeven van HTML- en XML-documenten. De DOM heeft zijn eigen API voor het werken met het weergegeven document: om het weergegeven document (de inhoud, structuur en stijl) dynamisch te openen, te verplaatsen en bij te werken. Wijzigingen in de DOM kunnen dynamisch worden doorgevoerd via JavaScript. En deze wijzigingen worden onmiddellijk weerspiegeld in de browser.

    Dankzij DOM kunnen webpagina's die in de browser worden geladen, stap voor stap worden bijgewerkt terwijl gegevens vanaf de server worden geladen. Dit gemak heeft echter ook een keerzijde: vooral de codefragmenten die verantwoordelijk zijn voor de dynamische interactie tussen JS en de DOM zijn foutgevoelig.

    De meest voorkomende fouten in webapplicaties

    Complexe gebeurtenisinteracties

    JavaScript is een gebeurtenisgestuurde taal. Hiermee kunnen ontwikkelaars zogenaamde gebeurtenislisteners op DOM-knooppunten registreren. Hoewel de meeste gebeurtenissen worden geactiveerd door gebruikersactie, zijn er enkele die ook zonder actie kunnen worden geactiveerd, zoals getimede gebeurtenissen en asynchrone oproepen. In dit geval kan elke gebeurtenis door de hele DOM-boom heen echoën en meerdere “luisteraars” tegelijk activeren. Soms is het bijhouden van dit alles een nogal niet-triviale taak.

    Hoe gebeurtenissen worden verwerkt

    Om deze redenen kan JS-code moeilijk te begrijpen, analyseren en testen zijn. Speciale hulpprogramma's maken het leven van een webontwikkelaar gemakkelijker en helpen u bij het schrijven van veilige code.

    Hulpprogramma's voor het testen van JS-code

    Er zijn hulpprogramma's voor parseren (bijv. Esprima, Rhino), optimalisatie (bijv. Google Closure Compiler) en statische code-analyse voor veelvoorkomende syntaxisfouten (bijv. JSHint).

    Bovendien zijn er verschillende beproefde raamwerken die webontwikkelaars helpen JS-code met tests te dekken. Onder hen:

    • QUnit is een populair raamwerk voor unit-testen;
    • Jasmine - BDD-framework (Behavior-driven Development) voor het testen van code;
    • Mocha is een raamwerk voor het testen van code, draait zowel in Node.js als in de browser;
    • jsTestDriver is een raamwerk dat onder andere een reeks tests in meerdere browsers tegelijk kan uitvoeren.

    Daarnaast zijn er testframeworks die browsergedrag emuleren en waarmee u automatisch testcases kunt uitvoeren. Ze zijn vooral relevant bij het debuggen van delen van de code die verantwoordelijk zijn voor de interactie tussen JS en de DOM, en bieden een handige infrastructuur voor het manipuleren van de DOM.

    Selenium, PhantomJS en SlimerJS bieden bijvoorbeeld een API waarmee u browserinstanties kunt starten en ermee kunt communiceren. Via de API kunt u gebeurtenissen activeren en rechtstreeks toegang krijgen tot DOM-elementen tijdens runtime - dat wil zeggen: u kunt de code testen onder omstandigheden die zo dicht mogelijk bij de echte liggen. Natuurlijk zal een aanzienlijk deel van het werk handmatig moeten worden gedaan, maar zelfs dit is een goede hulp bij het testen.

    Hulpprogramma's voor statische analyse

    Voorheen waren hulpprogramma's voor het identificeren van probleemgebieden in de code statische analysatoren. Dat wil zeggen dat ze, gezien alle dynamische eigenaardigheden van JS, slechts beperkte hulp konden bieden. Ze kunnen echter ook nuttig zijn bij analyses. Hier zijn enkele basisvoorbeelden.

    WARI is een statische analyser die de afhankelijkheden tussen JS-functies, CSS-stijlen, HTML-tags en afbeeldingen onderzoekt. Het doel van dit hulpprogramma is om ongebruikte bronnen te vinden tijdens statische analyse. Maar WARI kan de dynamiek uiteraard niet aan.

    JSLint is een hulpprogramma voor het analyseren van statische code dat zelf in JavaScript is geschreven. Het toetst de code aan goede praktijken.

    Google Closure Compiler is een JS-optimalisatieprogramma dat code automatisch herschrijft om het sneller en compacter te maken. Tegelijkertijd gaan alle opmerkingen en ongebruikte codegedeelten verloren.

    WebScent (zie wetenschappelijk werk) is een geavanceerde statische analysator. In zijn werk gaat hij ervan uit dat de client-JS-code (degene die in de browser wordt geladen) niet in zijn geheel op de server wordt opgeslagen, maar in stukjes over de servercode wordt verspreid. De "geur" ​​in deze brokken kan niet eenvoudig worden gedetecteerd totdat de volledige clientcode daaruit is gegenereerd. WebScent analyseert clientcode om probleemgebieden in servercode te vinden. Tegelijkertijd komt het werk van de statische analyser van WebScent vooral neer op het ontrafelen van de puinhoop van HTML, CSS en JS - om dubbele code en fouten in de HTML-syntaxis op te sporen.

    Hulpprogramma's voor dynamische analyse

    JSNose is een hulpprogramma dat statische en dynamische analyse combineert. Het analyseert de code voor dertien antipatronen. Zeven daarvan (inclusief lazy object en long function) zijn gemeenschappelijk voor alle programmeertalen, en de overige zes (sluitingsgeuren, overmatige globale variabelen, geneste callbacks en andere) zijn specifiek voor JavaScript.

    DOMPletion is een geautomatiseerd hulpprogramma dat webontwikkelaars helpt code te begrijpen terwijl ze deze beoordelen: legt uit waarom DOM-structuren aanwezig zijn, voert dynamische analyses uit en biedt slimme automatische aanvulling voor code die samenwerkt met de DOM.

    Clematis is een raamwerk dat helpt bij het ontrafelen van complexe gebeurtenisinteracties. Clematis legt in detail alle gebeurtenissen vast die tijdens de uitvoering worden geactiveerd en visualiseert deze in de vorm van een abstract gedragsmodel dat de temporele en oorzaak-en-gevolgrelaties tussen componenten en gebeurtenissen weerspiegelt.

    Conclusies

    Het kan dus moeilijk zijn om bij te houden wat er gebeurt bij het uitvoeren van scripts in JS, maar met de juiste tools kun je zelfs in de meest verwarrende code probleemgebieden vinden en herschrijven. JavaScript staat echter niet stil: er verschijnen nieuwe en nieuwe features in, nu wordt het vaak gebruikt om applicaties te schrijven (zowel mobiel als desktop), en wordt het dankzij Node.js ook steeds vaker op servers gevonden (en niet alleen). Dit betekent dat de kunst van het vangen van insecten naar een nieuw niveau moet worden getild.