Identificare errori di accesso alle proprietà in JavaScript
Un metodo per trovare errori comuni nell'accesso alle proprietà di JavaScript.
― 6 leggere min
Indice
In JavaScript, le proprietà degli oggetti possono cambiare in qualsiasi momento. Questa flessibilità rende facile per i programmatori fare errori che potrebbero rimanere nascosti per un sacco di tempo. Un problema comune è quando un programmatore prova a usare una proprietà che non esiste su un oggetto. Poiché JavaScript non genera un errore quando accesso a una proprietà non esistente, questi problemi possono essere difficili da individuare e correggere.
Questo articolo parla di un metodo per trovare questi errori di accesso alle proprietà. Il metodo è composto da due parti principali: raccogliere dati su come vengono usate le proprietà nel codice JavaScript reale e analizzare quei dati per identificare potenziali errori.
Perché Accadono Errori di Accesso alle Proprietà
JavaScript consente ai programmatori di modificare liberamente gli oggetti. Questo significa che le proprietà possono essere aggiunte, modificate o rimosse in qualsiasi momento durante la vita del programma. Anche se questa caratteristica è utile, consente anche di fare errori. Ad esempio, un semplice errore di battitura può portare a fare riferimento a una proprietà che non esiste.
Quando uno sviluppatore scrive codice, potrebbe non testare ogni possibile caso, rendendo facile trascurare questi errori. Invece di bloccarsi, JavaScript restituisce "undefined" quando si tenta di accedere a una proprietà che non c'è. Questo rende difficile per gli sviluppatori sapere quando hanno commesso un errore.
Esempi di Errori di Accesso alle Proprietà
Ecco alcuni esempi per illustrare come si possono sviluppare questi errori:
- Nome della Proprietà Errato: Se uno sviluppatore scrive per sbaglio - object.size(), ma il metodo corretto è- object.length, il programma può funzionare senza bloccarsi, ma non si comporterà come previsto.
- Proprietà Dinamiche: In alcuni casi, le librerie consentono agli utenti di aggiungere dinamicamente proprietà agli oggetti. Uno sviluppatore potrebbe assumere che una certa proprietà esisterà sempre quando in realtà potrebbe non esserci. 
- Accesso Condizionale: A volte, gli sviluppatori controllano se una proprietà è disponibile prima di accedervi. Se lo fanno in modo errato, potrebbero comunque incappare in errori. 
Questi tipi di problemi possono portare a bug difficili da risalire alla fonte.
Approccio in Due Fasi per Trovare Errori
Il metodo proposto per identificare errori di accesso alle proprietà consiste in due fasi principali: raccolta dei dati e Analisi Statistica.
Fase 1: Raccolta dei Dati
Nella prima fase, raccogliamo dati su come vengono accessi le proprietà in vari progetti JavaScript. Lo facciamo esaminando una vasta gamma di campioni di codice reale. Analizzando molti codebase, possiamo scoprire quali proprietà sono usate correttamente e quali sono meno comuni o potenzialmente errate.
Raccogliamo "modelli di accesso", che mostrano come vengono tipicamente accessi le proprietà degli oggetti. Ad esempio, se vediamo che fs.readFile viene usato frequentemente rispetto a fs.size, possiamo dedurre che il primo è più probabile che sia corretto, mentre il secondo potrebbe essere errato o meno comune.
Fase 2: Analisi Statistica
Nella seconda fase, analizziamo i dati raccolti. Controlliamo quanto spesso viene usata una proprietà in relazione al suo oggetto. Se troviamo che una determinata proprietà è usata molto meno frequentemente di quanto ci si aspetterebbe, potrebbe essere un segnale di errore.
L'analisi coinvolge diversi passaggi:
- Classificazione: Classifichiamo gli accessi alle proprietà in base a quanto sono comuni. Se una proprietà è usata molto con un oggetto specifico, è probabile che sia corretta. Se viene usata pochissimo, potrebbe indicare un problema. 
- Filtraggio: Non ogni accesso poco comune significa che c'è un bug. Alcune proprietà potrebbero essere raramente usate ma comunque valide a causa di contesti specifici nel codice. Quindi, applichiamo controlli aggiuntivi per filtrare i falsi allarmi. 
- Euristiche: Usciamo con regole empiriche per decidere se un accesso è probabilmente errato o meno. Ad esempio, se l'esistenza di una proprietà è confermata da un controllo condizionale, sappiamo di non classificarlo come un bug. 
Combinando queste due fasi, miriamo a creare un sistema robusto per rilevare errori di accesso alle proprietà.
Efficacia dell'Approccio
Per vedere quanto funziona bene il nostro approccio, abbiamo condotto esperimenti utilizzando dati provenienti da molti progetti JavaScript. In questi esperimenti, ci siamo posti l'obiettivo di quantificare quanti errori di accesso alle proprietà potevamo trovare e quanto accuratamente potevamo identificarli.
Misure Statistiche
Abbiamo usato termini comuni della statistica per misurare la nostra efficacia:
- Precisione: Questo ci dice quanti degli accessi alle proprietà segnalati erano realmente errori.
- Richiamo: Questo mostra quanti errori reali siamo riusciti a trovare nella nostra analisi.
Un'alta precisione significa che quando segnaliamo un potenziale errore, nella maggior parte dei casi è davvero un errore. Un alto richiamo significa che catturiamo la maggior parte dei bug reali esistenti.
Risultati degli Esperimenti
Nei nostri esperimenti, abbiamo scoperto che il nostro metodo poteva individuare efficacemente un gran numero di errori di accesso alle proprietà. Abbiamo raggiunto un punteggio di precisione superiore all'80%, il che significa che la maggior parte degli accessi segnalati era effettivamente un errore. Anche il nostro punteggio di richiamo è stato impressionante, indicando che abbiamo catturato una parte significativa degli errori nel codice.
Limitazioni degli Strumenti Attuali
Molti sviluppatori fanno affidamento su ambienti di sviluppo integrati (IDE), come VSCode, per aiutarli a scrivere codice. Questi strumenti spesso forniscono suggerimenti per il completamento del codice per aiutare gli sviluppatori a evitare errori di battitura. Tuttavia, le nostre scoperte indicano che questi suggerimenti non sono sempre affidabili.
Suggerimenti di VSCode
Nel testare la capacità di VSCode di suggerire proprietà, abbiamo scoperto che, mentre non ha mai suggerito proprietà errate, spesso non forniva i suggerimenti giusti. Su 100 accessi alle proprietà che abbiamo valutato, VSCode ha suggerito la proprietà corretta solo 18 volte. Questo dà un punteggio di richiamo basso, il che significa che gli sviluppatori non possono fare affidamento solo su questi suggerimenti per l'accuratezza.
Conclusione
Gli errori di accesso alle proprietà in JavaScript possono essere difficili da individuare, ma il nostro approccio in due fasi fornisce uno strumento utile per identificare questi errori. Raccogliendo dati estesi e applicando un'analisi statistica approfondita, possiamo individuare dove gli sviluppatori potrebbero andare storti.
Sebbene strumenti attuali come VSCode siano utili, non sono sufficienti da soli per catturare tutti i potenziali errori di accesso alle proprietà. Pertanto, il nostro metodo funge da complemento prezioso alle soluzioni esistenti, consentendo agli sviluppatori di scrivere codice più pulito e affidabile.
Titolo: A statistical approach for finding property-access errors
Estratto: We study the problem of finding incorrect property accesses in JavaScript where objects do not have a fixed layout, and properties (including methods) can be added, overwritten, and deleted freely throughout the lifetime of an object. Since referencing a non-existent property is not an error in JavaScript, accidental accesses to non-existent properties (caused, perhaps, by a typo or by a misunderstanding of API documentation) can go undetected without thorough testing, and may manifest far from the source of the problem. We propose a two-phase approach for detecting property access errors based on the observation that, in practice, most property accesses will be correct. First a large number of property access patterns is collected from an extensive corpus of real-world JavaScript code, and a statistical analysis is performed to identify anomalous usage patterns. Specific instances of these patterns may not be bugs (due, e.g., dynamic type checks), so a local data-flow analysis filters out instances of anomalous property accesses that are safe and leaves only those likely to be actual bugs. We experimentally validate our approach, showing that on a set of 100 concrete instances of anomalous property accesses, the approach achieves a precision of 82% with a recall of 90%, making it suitable for practical use. We also conducted an experiment to determine how effective the popular VSCode code completion feature is at suggesting object properties, and found that, while it never suggested an incorrect property (precision of 100%), it failed to suggest the correct property in 62 out of 80 cases (recall of 22.5%). This shows that developers cannot rely on VSCode's code completion alone to ensure that all property accesses are valid.
Autori: Ellen Arteca, Max Schäfer, Frank Tip
Ultimo aggiornamento: 2023-06-14 00:00:00
Lingua: English
URL di origine: https://arxiv.org/abs/2306.08741
Fonte PDF: https://arxiv.org/pdf/2306.08741
Licenza: https://creativecommons.org/licenses/by/4.0/
Modifiche: Questa sintesi è stata creata con l'assistenza di AI e potrebbe presentare delle imprecisioni. Per informazioni accurate, consultare i documenti originali collegati qui.
Si ringrazia arxiv per l'utilizzo della sua interoperabilità ad accesso aperto.
Link di riferimento
- https://github.com/isaacs/node-graceful-fs/blob/95ec3a283dffe0402282ea92f2356d3c166f6392/test/stats-uid-gid.js
- https://github.com/matthewp/fs/blob/869bb9509549a74b39d8d9efcbee025de479ec72/lib/core.js#L114
- https://github.com/codeclimate/javascript-test-reporter/blob/1ad7ea8ad010d59997fdfdb1e25bac9a78c38fda/formatter.js#L80
- https://github.com/worldline/3loc/blob/f24612bee2d3832aace40fe150c794334924c61d/test/actions/listen.js#L276
- https://www.chaijs.com/api/bdd/
- https://github.com/nodulusteam/-nodulus-codulus/blob/master/routes/codulus.js#L50
- https://dl.acm.org/ccs.cfm
- https://doi.org/10.5281/zenodo.7570291
- https://doi.org/10.5281/zenodo.6525941
- https://github.com/Nextdoor/ndscheduler/blob/d31016aaca480e38a69d75a66a9978a937c6a0b0/ndscheduler/static/js/models/job.js
- https://github.com/nodulusteam/-nodulus-codulus/blob/master/routes/codulus.js
- https://github.com/the-road-to-graphql/fullstack-apollo-express-mongodb-boilerplate/blob/7e5e9088ebe1193ec6df20975100d39bdd798666/src/tests/user.spec.js
- https://github.com/bcho04/galeforce/blob/547d70301e34ff52dfd9add6b6fdafeb1ec35db7/src/galeforce/actions/action.ts
- https://github.com/ariya/phantomjs/blob/0a0b0facb16acfbabb7804822ecaf4f4b9dce3d2/test/module/fs/paths.js
- https://github.com/Himself65/vscode-hentai/blob/b1056f7a4c3993fa87f069c329b322fc3ec4bf4d/src/hentai.ts
- https://github.com/HouseOps/HouseOps/blob/95a6b6fe74c101e93c30d9cb87856f3e0482e5c7/app/containers/ProcessesList.js
- https://github.com/fueledbydreams/zeit-codeclimate-integration/blob/master/src/views/overview.js
- https://github.com/banfstory/React-Forum-Frontend/blob/main/react_frontend/src/components/Forum.jsx
- https://github.com/fueledbydreams/zeit-codeclimate-integration/blob/master/src/index.js
- https://github.com/dawnwords/github-pr-auto-merge/blob/master/lib/auto-merger.js
- https://github.com/rajatonit/weatherApp/blob/master/search/search.js
- https://github.com/jeffreymeng/montavistamun/blob/master/src/components/registration/FormUpload.tsx
- https://github.com/rsksmart/rif-data-vault/blob/develop/modules/ipfs-cpinner-client/src/index.ts
- https://github.com/zix99/simple-auth/blob/master/tests/api/v1/oauth2.js
- https://github.com/tobilg/facebook-events-by-location-core/blob/master/lib/eventSearch.js
- https://github.com/Azure/blackbelt-aks-hackfest/blob/master/app/web/src/components/Leaderboard.vue
- https://github.com/statping/statping/blob/dev/frontend/src/forms/Notifier.vue
- https://github.com/rsksmart/rif-identity.js/blob/develop/packages/rif-id-core/src/operations/authentication.ts
- https://github.com/tiangolo/full-stack-flask-couchdb/blob/master/
- https://github.com/olegp/common-node/blob/master/lib/fs-base.js
- https://github.com/browserify/browserify/blob/0ec6e80ec48b67513718a392a6d09bd5569967d4/index.js
- https://github.com/mozilla/openbadges-bakery/blob/master/lib/stream-type-check.js
- https://github.com/opbeat/opbeat-node/blob/09c99083d067fe8084a311f69a9655c1e850dbe2/lib/instrumentation/shimmer.js
- https://github.com/Alhadis/Utils/blob/master/test/shell.mjs
- https://github.com/webtorrent/create-torrent/blob/master/index.js
- https://github.com/MadLittleMods/postcss-css-variables/blob/master/playground/jspm_packages/system.src.js
- https://github.com/jh12z/codegen/blob/master/lib/codegen.js
- https://github.com/node-modules/compressing/blob/321d9d577b97f6a96fbf6d9c6a46655349a790d5/lib/tar/stream.js
- https://github.com/mozilla/openbadges-bakery/blob/master/lib/svg.js
- https://github.com/highcharts/node-export-server/blob/master/tests/http/side-by-side.js
- https://github.com/mholt/PapaParse/blob/master/papaparse.js
- https://github.com/subtleGradient/node-junitreport/blob/master/parse.js
- https://github.com/willnewii/qiniuClient/blob/master/src/main/util/qetag.js
- https://github.com/TooTallNate/node-get-uri/blob/c9ced38f67b1911b890117696215103a54d001a9/src/file.ts
- https://github.com/regl-project/regl/blob/104e83225336666d29f5d2a6534e837d3b6f5f04/bin/build-gallery.js
- https://github.com/krakenjs/spud/blob/851858ad1824b1907777580eef61fdcdb3d700d2/lib/transcoder.js
- https://github.com/Kong/unirest-nodejs/blob/a06ba4e6c58fea028d377c170cb4cbf7cf3c6049/index.js
- https://github.com/anupamroy/Engage-App-Codebase-Clean/blob/master/users/engagecalci/fullcalendar.js
- https://github.com/tidysource/tidypath/blob/c5dee736d966aaa00c2885f33d4ce98e900315c7/index.js
- https://github.com/jonschlinkert/add-filename-increment/blob/master/test/linux.js
- https://github.com/uber-archive/npm-shrinkwrap/blob/master/analyze-dependency.js
- https://github.com/jonschlinkert/strip-filename-increment/blob/master/index.js
- https://github.com/unifiedjs/unified-engine/blob/91ba25d0355fdb8a57e90be8141d04f42295eec3/lib/finder.js
- https://github.com/bigeasy/timezone/blob/bffc3c12823d61d342492a61951a3e8229e08e18/util/localizer.js
- https://github.com/async-library/react-async/blob/af52ec3491b9648ead9ec1dce66a75a2bf44cbc2/packages/react-async/src/propTypes.ts
- https://github.com/prose/prose/blob/370fe86574684dfcb72b27ffee0ca0ff787114dd/app/models/file.js
- https://github.com/dimagi/Vellum/blob/23e50bd2110a8457705c4f75aadbb4e1e13ef283/src/core.js
- https://github.com/strongloop/strong-log-transformer/blob/master/test/common.js
- https://github.com/pull-stream/stream-to-pull-stream/blob/master/index.js
- https://github.com/kevinchen8621/temple/blob/master/lib/qiniu/upload.js
- https://github.com/jonschlinkert/copy/blob/master/lib/dest.js
- https://github.com/import-js/eslint-plugin-import/blob/add650a1aeb118a4334bf2e9c56699ba1a836565/resolvers/webpack/index.js
- https://github.com/joao-neves95/merger-js/blob/master/modules/fileDownloader.js
- https://github.com/plopjs/node-plop/blob/master/src/actions/_common-action-utils.js
- https://github.com/simov/request-compose/blob/master/request/length.js
- https://github.com/WenlinMao/Furnitrade/blob/master/source/react/src/components/uploadImg/UploadImg.js
- https://github.com/node-modules/compressing/blob/master/lib/tar/uncompress_stream.js
- https://github.com/glslify/glslify-deps/blob/master/index.js
- https://github.com/albertosantini/node-rio/blob/master/lib/main.js
- https://github.com/nasa/cmr-stac/blob/master/search/lib/cmr.js
- https://github.com/mjackson/bufferedstream/blob/master/index.js
- https://github.com/Unitech/gridcontrol/blob/master/grid-cli/lib/common.js
- https://github.com/jonschlinkert/parse-filepath/blob/master/test.js
- https://github.com/Kong/unirest-nodejs/blob/master/index.js
- https://github.com/ymyang/fdfs/blob/master/lib/storage.js
- https://github.com/broccolijs/broccoli-persistent-filter/blob/master/src/dependencies.ts
- https://github.com/jonschlinkert/parse-filepath/blob/master/index.js
- https://github.com/07akioni/cxsjsw-hw6/blob/master/fe/src/components/Order.js
- https://github.com/EllarDevelopment/csv-manipulation-tool/blob/master/index.js
- https://github.com/nodeWechat/wechat4u/blob/master/src/core.js
- https://github.com/hyperledger-archives/composer-sample-applications/blob/master/packages/letters-of-credit/src/components/Pages/AlicePage/AlicePage.js
- https://github.com/joyent/node-http-signature/blob/master/test/examples.test.js
- https://github.com/jakutis/httpinvoke/blob/master/Gruntfile.js
- https://github.com/pgte/pipeline/blob/master/pipeline.js
- https://github.com/nrstott/bogart/blob/master/lib/bogart.js
- https://github.com/apigee-127/swagger-test-templates/blob/24a109434cefd020d45f37d9a05058bc564f2a52/test/robust/compare/supertest/assert/base-path-test.js
- https://github.com/justadudewhohacks/face-recognition.js/blob/409ffd82793784bbb633621aa463df2a62936407/tests/FaceRecognizer/FaceRecognizerTest.js
- https://github.com/steos/reactcards/blob/e8948586a0e6a864eb5dea0f324b1c3ed630c585/test/cards.test.js
- https://github.com/paypal/legalize.js/blob/3389d5b1a1e81087888b82766e7aab19bdba45c0/test/reporting.test.js
- https://github.com/worldline/3loc/blob/f24612bee2d3832aace40fe150c794334924c61d/test/actions/listen.js
- https://github.com/lucybot/jammin/blob/9dd13ae23608681385801eb835f31aef499d6839/test/petstore.js
- https://github.com/mklabs/node-build-script/blob/c5cbcabd829971139f9da4e1334a782950d931a1/test/helpers/index.js
- https://github.com/fshost/node-dir/blob/a57c3b1b571dd91f464ae398090ba40f64ba38a2/test/test.js
- https://github.com/codeclimate/javascript-test-reporter/blob/1ad7ea8ad010d59997fdfdb1e25bac9a78c38fda/formatter.js
- https://github.com/cibernox/ember-power-datepicker/blob/da580474a2c449b715444934ddb626b7c07f46a7/tests/dummy/app/controllers/public-pages/index.js
- https://github.com/tarunyadav1/Doist-React-App-Using-firebase/blob/411010c0aac52502daa5bd5a63a1601fad0f29b2/src/components/AddTask.js
- https://github.com/socketstream/socketstream/blob/790bfbd20cda239e20dba6ed7f05425438c030e8/lib/client/bundler/proto.js
- https://github.com/matthewp/fs/blob/869bb9509549a74b39d8d9efcbee025de479ec72/lib/core.js
- https://github.com/Giveth/milestonetracker-ui/blob/5b0d40900610a799e77ba76d2fa609289fad2c60/dapp/js/components/DeploymentResults.jsx
- https://github.com/webcaetano/shuffle-seed/blob/2cc884d70ef08cce809e9d166a1c8081cf8fec3e/test.js
- https://github.com/js-kyle/mincer/blob/c7791df2605fbca423fd24684d5f421e0da8e8fc/lib/mincer/assets/bundled.js
- https://github.com/levelgraph/levelgraph-jsonld/blob/075945bd39fd30decba182dc7b089f1b3f04d1c4/test/get_spec.js
- https://github.com/rsksmart/rif-data-vault/blob/develop/modules/ipfs-cpinner-client/src/index.ts#L37
- https://github.com/jeffreymeng/montavistamun/blob/master/src/components/registration/FormUpload.tsx#L53
- https://github.com/rsksmart/rif-identity.js/blob/develop/packages/rif-id-core/src/operations/authentication.ts#L36
- https://github.com/async-library/react-async/blob/af52ec3491b9648ead9ec1dce66a75a2bf44cbc2/packages/react-async/src/propTypes.ts#L51
- https://github.com/Giveth/milestonetracker-ui
- https://github.com/StateOfJS/StateOfJS-2019
- https://github.com/YaleDHLab/intertext
- https://github.com/chifei/spring-demo-project
- https://github.com/async-library/react-async
- https://github.com/TooTallNate/node-get-uri
- https://github.com/SUI-Components/sui
- https://github.com/krakenjs/spud
- https://github.com/lakenen/node-box-view
- https://github.com/airtap/airtap
- https://github.com/jeffpar/pcjs
- https://github.com/yeoman/stringify-object
- https://github.com/mklabs/node-build-script
- https://github.com/node-gfx/node-canvas-prebuilt
- https://github.com/marko-js-archive/async-writer
- https://github.com/mbostock/gistup
- https://github.com/marionebl/share-cli
- https://github.com/minio/minio-js
- https://github.com/mieweb/wikiGDrive
- https://github.com/meyda/meyda
- https://github.com/electrodejs/deprecated-generator-electrode
- https://github.com/endpoints/endpoints
- https://github.com/cooliejs/coolie-cli
- https://github.com/codeclimate/javascript-test-reporter
- https://github.com/architectcodes/6-to-library
- https://github.com/ariya/phantomjs
- https://github.com/bigeasy/timezone
- https://github.com/wp-pot/wp-pot
- https://github.com/vanwagonet/modules
- https://github.com/tessel/t1-cli
- https://github.com/substance/dar-server
- https://github.com/pulumi/docs
- https://github.com/opbeat/opbeat-node
- https://github.com/npm/cacache
- https://github.com/smhg/gettext-parser
- https://github.com/Alhadis/Utils
- https://github.com/atlassianlabs/ac-koa-hipchat
- https://github.com/auth0/node-jws
- https://github.com/webtorrent/create-torrent
- https://github.com/albertosantini/node-rio
- https://github.com/nodemailer/nodemailer
- https://github.com/facebookarchive/jsgrep
- https://github.com/christkv/node-git
- https://github.com/cj/node-sd-api
- https://github.com/dmester/jdenticon
- https://github.com/mayflower/PHProjekt
- https://github.com/devongovett/node-wkhtmltopdf
- https://github.com/tarranjones/macOS-defaults
- https://github.com/Kong/unirest-nodejs
- https://github.com/twbs/icons