jetbrains.patch 193 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468
  1. diff --git a/src/main.ts b/src/main.ts
  2. deleted file mode 100644
  3. index 1af3c941e00..00000000000
  4. --- a/src/main.ts
  5. +++ /dev/null
  6. @@ -1,719 +0,0 @@
  7. -/*---------------------------------------------------------------------------------------------
  8. - * Copyright (c) Microsoft Corporation. All rights reserved.
  9. - * Licensed under the MIT License. See License.txt in the project root for license information.
  10. - *--------------------------------------------------------------------------------------------*/
  11. -
  12. -import * as path from 'path';
  13. -import * as fs from 'original-fs';
  14. -import * as os from 'os';
  15. -import { performance } from 'perf_hooks';
  16. -import { configurePortable } from './bootstrap-node.js';
  17. -import { bootstrapESM } from './bootstrap-esm.js';
  18. -import { fileURLToPath } from 'url';
  19. -import { app, protocol, crashReporter, Menu, contentTracing } from 'electron';
  20. -import minimist from 'minimist';
  21. -import { product } from './bootstrap-meta.js';
  22. -import { parse } from './vs/base/common/jsonc.js';
  23. -import { getUserDataPath } from './vs/platform/environment/node/userDataPath.js';
  24. -import * as perf from './vs/base/common/performance.js';
  25. -import { resolveNLSConfiguration } from './vs/base/node/nls.js';
  26. -import { getUNCHost, addUNCHostToAllowlist } from './vs/base/node/unc.js';
  27. -import { INLSConfiguration } from './vs/nls.js';
  28. -import { NativeParsedArgs } from './vs/platform/environment/common/argv.js';
  29. -
  30. -const __dirname = path.dirname(fileURLToPath(import.meta.url));
  31. -
  32. -perf.mark('code/didStartMain');
  33. -
  34. -perf.mark('code/willLoadMainBundle', {
  35. - // When built, the main bundle is a single JS file with all
  36. - // dependencies inlined. As such, we mark `willLoadMainBundle`
  37. - // as the start of the main bundle loading process.
  38. - startTime: Math.floor(performance.timeOrigin)
  39. -});
  40. -perf.mark('code/didLoadMainBundle');
  41. -
  42. -// Enable portable support
  43. -const portable = configurePortable(product);
  44. -
  45. -const args = parseCLIArgs();
  46. -// Configure static command line arguments
  47. -const argvConfig = configureCommandlineSwitchesSync(args);
  48. -// Enable sandbox globally unless
  49. -// 1) disabled via command line using either
  50. -// `--no-sandbox` or `--disable-chromium-sandbox` argument.
  51. -// 2) argv.json contains `disable-chromium-sandbox: true`.
  52. -if (args['sandbox'] &&
  53. - !args['disable-chromium-sandbox'] &&
  54. - !argvConfig['disable-chromium-sandbox']) {
  55. - app.enableSandbox();
  56. -} else if (app.commandLine.hasSwitch('no-sandbox') &&
  57. - !app.commandLine.hasSwitch('disable-gpu-sandbox')) {
  58. - // Disable GPU sandbox whenever --no-sandbox is used.
  59. - app.commandLine.appendSwitch('disable-gpu-sandbox');
  60. -} else {
  61. - app.commandLine.appendSwitch('no-sandbox');
  62. - app.commandLine.appendSwitch('disable-gpu-sandbox');
  63. -}
  64. -
  65. -// Set userData path before app 'ready' event
  66. -const userDataPath = getUserDataPath(args, product.nameShort ?? 'code-oss-dev');
  67. -if (process.platform === 'win32') {
  68. - const userDataUNCHost = getUNCHost(userDataPath);
  69. - if (userDataUNCHost) {
  70. - addUNCHostToAllowlist(userDataUNCHost); // enables to use UNC paths in userDataPath
  71. - }
  72. -}
  73. -app.setPath('userData', userDataPath);
  74. -
  75. -// Resolve code cache path
  76. -const codeCachePath = getCodeCachePath();
  77. -
  78. -// Disable default menu (https://github.com/electron/electron/issues/35512)
  79. -Menu.setApplicationMenu(null);
  80. -
  81. -// Configure crash reporter
  82. -perf.mark('code/willStartCrashReporter');
  83. -// If a crash-reporter-directory is specified we store the crash reports
  84. -// in the specified directory and don't upload them to the crash server.
  85. -//
  86. -// Appcenter crash reporting is enabled if
  87. -// * enable-crash-reporter runtime argument is set to 'true'
  88. -// * --disable-crash-reporter command line parameter is not set
  89. -//
  90. -// Disable crash reporting in all other cases.
  91. -if (args['crash-reporter-directory'] || (argvConfig['enable-crash-reporter'] && !args['disable-crash-reporter'])) {
  92. - configureCrashReporter();
  93. -}
  94. -perf.mark('code/didStartCrashReporter');
  95. -
  96. -// Set logs path before app 'ready' event if running portable
  97. -// to ensure that no 'logs' folder is created on disk at a
  98. -// location outside of the portable directory
  99. -// (https://github.com/microsoft/vscode/issues/56651)
  100. -if (portable && portable.isPortable) {
  101. - app.setAppLogsPath(path.join(userDataPath, 'logs'));
  102. -}
  103. -
  104. -// Register custom schemes with privileges
  105. -protocol.registerSchemesAsPrivileged([
  106. - {
  107. - scheme: 'vscode-webview',
  108. - privileges: { standard: true, secure: true, supportFetchAPI: true, corsEnabled: true, allowServiceWorkers: true, codeCache: true }
  109. - },
  110. - {
  111. - scheme: 'vscode-file',
  112. - privileges: { secure: true, standard: true, supportFetchAPI: true, corsEnabled: true, codeCache: true }
  113. - }
  114. -]);
  115. -
  116. -// Global app listeners
  117. -registerListeners();
  118. -
  119. -/**
  120. - * We can resolve the NLS configuration early if it is defined
  121. - * in argv.json before `app.ready` event. Otherwise we can only
  122. - * resolve NLS after `app.ready` event to resolve the OS locale.
  123. - */
  124. -let nlsConfigurationPromise: Promise<INLSConfiguration> | undefined = undefined;
  125. -
  126. -// Use the most preferred OS language for language recommendation.
  127. -// The API might return an empty array on Linux, such as when
  128. -// the 'C' locale is the user's only configured locale.
  129. -// No matter the OS, if the array is empty, default back to 'en'.
  130. -const osLocale = processZhLocale((app.getPreferredSystemLanguages()?.[0] ?? 'en').toLowerCase());
  131. -const userLocale = getUserDefinedLocale(argvConfig);
  132. -if (userLocale) {
  133. - nlsConfigurationPromise = resolveNLSConfiguration({
  134. - userLocale,
  135. - osLocale,
  136. - commit: product.commit,
  137. - userDataPath,
  138. - nlsMetadataPath: __dirname
  139. - });
  140. -}
  141. -
  142. -// Pass in the locale to Electron so that the
  143. -// Windows Control Overlay is rendered correctly on Windows.
  144. -// For now, don't pass in the locale on macOS due to
  145. -// https://github.com/microsoft/vscode/issues/167543.
  146. -// If the locale is `qps-ploc`, the Microsoft
  147. -// Pseudo Language Language Pack is being used.
  148. -// In that case, use `en` as the Electron locale.
  149. -
  150. -if (process.platform === 'win32' || process.platform === 'linux') {
  151. - const electronLocale = (!userLocale || userLocale === 'qps-ploc') ? 'en' : userLocale;
  152. - app.commandLine.appendSwitch('lang', electronLocale);
  153. -}
  154. -
  155. -// Load our code once ready
  156. -app.once('ready', function () {
  157. - if (args['trace']) {
  158. - let traceOptions: Electron.TraceConfig | Electron.TraceCategoriesAndOptions;
  159. - if (args['trace-memory-infra']) {
  160. - const customCategories = args['trace-category-filter']?.split(',') || [];
  161. - customCategories.push('disabled-by-default-memory-infra', 'disabled-by-default-memory-infra.v8.code_stats');
  162. - traceOptions = {
  163. - included_categories: customCategories,
  164. - excluded_categories: ['*'],
  165. - memory_dump_config: {
  166. - allowed_dump_modes: ['light', 'detailed'],
  167. - triggers: [
  168. - {
  169. - type: 'periodic_interval',
  170. - mode: 'detailed',
  171. - min_time_between_dumps_ms: 10000
  172. - },
  173. - {
  174. - type: 'periodic_interval',
  175. - mode: 'light',
  176. - min_time_between_dumps_ms: 1000
  177. - }
  178. - ]
  179. - }
  180. - };
  181. - } else {
  182. - traceOptions = {
  183. - categoryFilter: args['trace-category-filter'] || '*',
  184. - traceOptions: args['trace-options'] || 'record-until-full,enable-sampling'
  185. - };
  186. - }
  187. -
  188. - contentTracing.startRecording(traceOptions).finally(() => onReady());
  189. - } else {
  190. - onReady();
  191. - }
  192. -});
  193. -
  194. -async function onReady() {
  195. - perf.mark('code/mainAppReady');
  196. -
  197. - try {
  198. - const [, nlsConfig] = await Promise.all([
  199. - mkdirpIgnoreError(codeCachePath),
  200. - resolveNlsConfiguration()
  201. - ]);
  202. -
  203. - await startup(codeCachePath, nlsConfig);
  204. - } catch (error) {
  205. - console.error(error);
  206. - }
  207. -}
  208. -
  209. -/**
  210. - * Main startup routine
  211. - */
  212. -async function startup(codeCachePath: string | undefined, nlsConfig: INLSConfiguration): Promise<void> {
  213. - process.env['VSCODE_NLS_CONFIG'] = JSON.stringify(nlsConfig);
  214. - process.env['VSCODE_CODE_CACHE_PATH'] = codeCachePath || '';
  215. -
  216. - // Bootstrap ESM
  217. - await bootstrapESM();
  218. -
  219. - // Load Main
  220. - await import('./vs/code/electron-main/main.js');
  221. - perf.mark('code/didRunMainBundle');
  222. -}
  223. -
  224. -function configureCommandlineSwitchesSync(cliArgs: NativeParsedArgs) {
  225. - const SUPPORTED_ELECTRON_SWITCHES = [
  226. -
  227. - // alias from us for --disable-gpu
  228. - 'disable-hardware-acceleration',
  229. -
  230. - // override for the color profile to use
  231. - 'force-color-profile',
  232. -
  233. - // disable LCD font rendering, a Chromium flag
  234. - 'disable-lcd-text',
  235. -
  236. - // bypass any specified proxy for the given semi-colon-separated list of hosts
  237. - 'proxy-bypass-list'
  238. - ];
  239. -
  240. - if (process.platform === 'linux') {
  241. -
  242. - // Force enable screen readers on Linux via this flag
  243. - SUPPORTED_ELECTRON_SWITCHES.push('force-renderer-accessibility');
  244. -
  245. - // override which password-store is used on Linux
  246. - SUPPORTED_ELECTRON_SWITCHES.push('password-store');
  247. - }
  248. -
  249. - const SUPPORTED_MAIN_PROCESS_SWITCHES = [
  250. -
  251. - // Persistently enable proposed api via argv.json: https://github.com/microsoft/vscode/issues/99775
  252. - 'enable-proposed-api',
  253. -
  254. - // Log level to use. Default is 'info'. Allowed values are 'error', 'warn', 'info', 'debug', 'trace', 'off'.
  255. - 'log-level',
  256. -
  257. - // Use an in-memory storage for secrets
  258. - 'use-inmemory-secretstorage'
  259. - ];
  260. -
  261. - // Read argv config
  262. - const argvConfig = readArgvConfigSync();
  263. -
  264. - Object.keys(argvConfig).forEach(argvKey => {
  265. - const argvValue = argvConfig[argvKey];
  266. -
  267. - // Append Electron flags to Electron
  268. - if (SUPPORTED_ELECTRON_SWITCHES.indexOf(argvKey) !== -1) {
  269. - if (argvValue === true || argvValue === 'true') {
  270. - if (argvKey === 'disable-hardware-acceleration') {
  271. - app.disableHardwareAcceleration(); // needs to be called explicitly
  272. - } else {
  273. - app.commandLine.appendSwitch(argvKey);
  274. - }
  275. - } else if (typeof argvValue === 'string' && argvValue) {
  276. - if (argvKey === 'password-store') {
  277. - // Password store
  278. - // TODO@TylerLeonhardt: Remove this migration in 3 months
  279. - let migratedArgvValue = argvValue;
  280. - if (argvValue === 'gnome' || argvValue === 'gnome-keyring') {
  281. - migratedArgvValue = 'gnome-libsecret';
  282. - }
  283. - app.commandLine.appendSwitch(argvKey, migratedArgvValue);
  284. - } else {
  285. - app.commandLine.appendSwitch(argvKey, argvValue);
  286. - }
  287. - }
  288. - }
  289. -
  290. - // Append main process flags to process.argv
  291. - else if (SUPPORTED_MAIN_PROCESS_SWITCHES.indexOf(argvKey) !== -1) {
  292. - switch (argvKey) {
  293. - case 'enable-proposed-api':
  294. - if (Array.isArray(argvValue)) {
  295. - argvValue.forEach(id => id && typeof id === 'string' && process.argv.push('--enable-proposed-api', id));
  296. - } else {
  297. - console.error(`Unexpected value for \`enable-proposed-api\` in argv.json. Expected array of extension ids.`);
  298. - }
  299. - break;
  300. -
  301. - case 'log-level':
  302. - if (typeof argvValue === 'string') {
  303. - process.argv.push('--log', argvValue);
  304. - } else if (Array.isArray(argvValue)) {
  305. - for (const value of argvValue) {
  306. - process.argv.push('--log', value);
  307. - }
  308. - }
  309. - break;
  310. -
  311. - case 'use-inmemory-secretstorage':
  312. - if (argvValue) {
  313. - process.argv.push('--use-inmemory-secretstorage');
  314. - }
  315. - break;
  316. - }
  317. - }
  318. - });
  319. -
  320. - // Following features are enabled from the runtime:
  321. - // `DocumentPolicyIncludeJSCallStacksInCrashReports` - https://www.electronjs.org/docs/latest/api/web-frame-main#framecollectjavascriptcallstack-experimental
  322. - // `EarlyEstablishGpuChannel` - Refs https://issues.chromium.org/issues/40208065
  323. - // `EstablishGpuChannelAsync` - Refs https://issues.chromium.org/issues/40208065
  324. - const featuresToEnable =
  325. - `DocumentPolicyIncludeJSCallStacksInCrashReports,EarlyEstablishGpuChannel,EstablishGpuChannelAsync,${app.commandLine.getSwitchValue('enable-features')}`;
  326. - app.commandLine.appendSwitch('enable-features', featuresToEnable);
  327. -
  328. - // Following features are disabled from the runtime:
  329. - // `CalculateNativeWinOcclusion` - Disable native window occlusion tracker (https://groups.google.com/a/chromium.org/g/embedder-dev/c/ZF3uHHyWLKw/m/VDN2hDXMAAAJ)
  330. - const featuresToDisable =
  331. - `CalculateNativeWinOcclusion,${app.commandLine.getSwitchValue('disable-features')}`;
  332. - app.commandLine.appendSwitch('disable-features', featuresToDisable);
  333. -
  334. - // Blink features to configure.
  335. - // `FontMatchingCTMigration` - Siwtch font matching on macOS to Appkit (Refs https://github.com/microsoft/vscode/issues/224496#issuecomment-2270418470).
  336. - // `StandardizedBrowserZoom` - Disable zoom adjustment for bounding box (https://github.com/microsoft/vscode/issues/232750#issuecomment-2459495394)
  337. - const blinkFeaturesToDisable =
  338. - `FontMatchingCTMigration,StandardizedBrowserZoom,${app.commandLine.getSwitchValue('disable-blink-features')}`;
  339. - app.commandLine.appendSwitch('disable-blink-features', blinkFeaturesToDisable);
  340. -
  341. - // Support JS Flags
  342. - const jsFlags = getJSFlags(cliArgs);
  343. - if (jsFlags) {
  344. - app.commandLine.appendSwitch('js-flags', jsFlags);
  345. - }
  346. -
  347. - // Use portal version 4 that supports current_folder option
  348. - // to address https://github.com/microsoft/vscode/issues/213780
  349. - // Runtime sets the default version to 3, refs https://github.com/electron/electron/pull/44426
  350. - app.commandLine.appendSwitch('xdg-portal-required-version', '4');
  351. -
  352. - return argvConfig;
  353. -}
  354. -
  355. -interface IArgvConfig {
  356. - [key: string]: string | string[] | boolean | undefined;
  357. - readonly locale?: string;
  358. - readonly 'disable-lcd-text'?: boolean;
  359. - readonly 'proxy-bypass-list'?: string;
  360. - readonly 'disable-hardware-acceleration'?: boolean;
  361. - readonly 'force-color-profile'?: string;
  362. - readonly 'enable-crash-reporter'?: boolean;
  363. - readonly 'crash-reporter-id'?: string;
  364. - readonly 'enable-proposed-api'?: string[];
  365. - readonly 'log-level'?: string | string[];
  366. - readonly 'disable-chromium-sandbox'?: boolean;
  367. - readonly 'use-inmemory-secretstorage'?: boolean;
  368. -}
  369. -
  370. -function readArgvConfigSync(): IArgvConfig {
  371. -
  372. - // Read or create the argv.json config file sync before app('ready')
  373. - const argvConfigPath = getArgvConfigPath();
  374. - let argvConfig: IArgvConfig | undefined = undefined;
  375. - try {
  376. - argvConfig = parse(fs.readFileSync(argvConfigPath).toString());
  377. - } catch (error) {
  378. - if (error && error.code === 'ENOENT') {
  379. - createDefaultArgvConfigSync(argvConfigPath);
  380. - } else {
  381. - console.warn(`Unable to read argv.json configuration file in ${argvConfigPath}, falling back to defaults (${error})`);
  382. - }
  383. - }
  384. -
  385. - // Fallback to default
  386. - if (!argvConfig) {
  387. - argvConfig = {};
  388. - }
  389. -
  390. - return argvConfig;
  391. -}
  392. -
  393. -function createDefaultArgvConfigSync(argvConfigPath: string): void {
  394. - try {
  395. -
  396. - // Ensure argv config parent exists
  397. - const argvConfigPathDirname = path.dirname(argvConfigPath);
  398. - if (!fs.existsSync(argvConfigPathDirname)) {
  399. - fs.mkdirSync(argvConfigPathDirname);
  400. - }
  401. -
  402. - // Default argv content
  403. - const defaultArgvConfigContent = [
  404. - '// This configuration file allows you to pass permanent command line arguments to VS Code.',
  405. - '// Only a subset of arguments is currently supported to reduce the likelihood of breaking',
  406. - '// the installation.',
  407. - '//',
  408. - '// PLEASE DO NOT CHANGE WITHOUT UNDERSTANDING THE IMPACT',
  409. - '//',
  410. - '// NOTE: Changing this file requires a restart of VS Code.',
  411. - '{',
  412. - ' // Use software rendering instead of hardware accelerated rendering.',
  413. - ' // This can help in cases where you see rendering issues in VS Code.',
  414. - ' // "disable-hardware-acceleration": true',
  415. - '}'
  416. - ];
  417. -
  418. - // Create initial argv.json with default content
  419. - fs.writeFileSync(argvConfigPath, defaultArgvConfigContent.join('\n'));
  420. - } catch (error) {
  421. - console.error(`Unable to create argv.json configuration file in ${argvConfigPath}, falling back to defaults (${error})`);
  422. - }
  423. -}
  424. -
  425. -function getArgvConfigPath(): string {
  426. - const vscodePortable = process.env['VSCODE_PORTABLE'];
  427. - if (vscodePortable) {
  428. - return path.join(vscodePortable, 'argv.json');
  429. - }
  430. -
  431. - let dataFolderName = product.dataFolderName;
  432. - if (process.env['VSCODE_DEV']) {
  433. - dataFolderName = `${dataFolderName}-dev`;
  434. - }
  435. -
  436. - return path.join(os.homedir(), dataFolderName!, 'argv.json');
  437. -}
  438. -
  439. -function configureCrashReporter(): void {
  440. - let crashReporterDirectory = args['crash-reporter-directory'];
  441. - let submitURL = '';
  442. - if (crashReporterDirectory) {
  443. - crashReporterDirectory = path.normalize(crashReporterDirectory);
  444. -
  445. - if (!path.isAbsolute(crashReporterDirectory)) {
  446. - console.error(`The path '${crashReporterDirectory}' specified for --crash-reporter-directory must be absolute.`);
  447. - app.exit(1);
  448. - }
  449. -
  450. - if (!fs.existsSync(crashReporterDirectory)) {
  451. - try {
  452. - fs.mkdirSync(crashReporterDirectory, { recursive: true });
  453. - } catch (error) {
  454. - console.error(`The path '${crashReporterDirectory}' specified for --crash-reporter-directory does not seem to exist or cannot be created.`);
  455. - app.exit(1);
  456. - }
  457. - }
  458. -
  459. - // Crashes are stored in the crashDumps directory by default, so we
  460. - // need to change that directory to the provided one
  461. - console.log(`Found --crash-reporter-directory argument. Setting crashDumps directory to be '${crashReporterDirectory}'`);
  462. - app.setPath('crashDumps', crashReporterDirectory);
  463. - }
  464. -
  465. - // Otherwise we configure the crash reporter from product.json
  466. - else {
  467. - const appCenter = product.appCenter;
  468. - if (appCenter) {
  469. - const isWindows = (process.platform === 'win32');
  470. - const isLinux = (process.platform === 'linux');
  471. - const isDarwin = (process.platform === 'darwin');
  472. - const crashReporterId = argvConfig['crash-reporter-id'];
  473. - const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
  474. - if (crashReporterId && uuidPattern.test(crashReporterId)) {
  475. - if (isWindows) {
  476. - switch (process.arch) {
  477. - case 'x64':
  478. - submitURL = appCenter['win32-x64'];
  479. - break;
  480. - case 'arm64':
  481. - submitURL = appCenter['win32-arm64'];
  482. - break;
  483. - }
  484. - } else if (isDarwin) {
  485. - if (product.darwinUniversalAssetId) {
  486. - submitURL = appCenter['darwin-universal'];
  487. - } else {
  488. - switch (process.arch) {
  489. - case 'x64':
  490. - submitURL = appCenter['darwin'];
  491. - break;
  492. - case 'arm64':
  493. - submitURL = appCenter['darwin-arm64'];
  494. - break;
  495. - }
  496. - }
  497. - } else if (isLinux) {
  498. - submitURL = appCenter['linux-x64'];
  499. - }
  500. - submitURL = submitURL.concat('&uid=', crashReporterId, '&iid=', crashReporterId, '&sid=', crashReporterId);
  501. - // Send the id for child node process that are explicitly starting crash reporter.
  502. - // For vscode this is ExtensionHost process currently.
  503. - const argv = process.argv;
  504. - const endOfArgsMarkerIndex = argv.indexOf('--');
  505. - if (endOfArgsMarkerIndex === -1) {
  506. - argv.push('--crash-reporter-id', crashReporterId);
  507. - } else {
  508. - // if the we have an argument "--" (end of argument marker)
  509. - // we cannot add arguments at the end. rather, we add
  510. - // arguments before the "--" marker.
  511. - argv.splice(endOfArgsMarkerIndex, 0, '--crash-reporter-id', crashReporterId);
  512. - }
  513. - }
  514. - }
  515. - }
  516. -
  517. - // Start crash reporter for all processes
  518. - const productName = (product.crashReporter ? product.crashReporter.productName : undefined) || product.nameShort;
  519. - const companyName = (product.crashReporter ? product.crashReporter.companyName : undefined) || 'Microsoft';
  520. - const uploadToServer = Boolean(!process.env['VSCODE_DEV'] && submitURL && !crashReporterDirectory);
  521. - crashReporter.start({
  522. - companyName,
  523. - productName: process.env['VSCODE_DEV'] ? `${productName} Dev` : productName,
  524. - submitURL,
  525. - uploadToServer,
  526. - compress: true
  527. - });
  528. -}
  529. -
  530. -function getJSFlags(cliArgs: NativeParsedArgs): string | null {
  531. - const jsFlags: string[] = [];
  532. -
  533. - // Add any existing JS flags we already got from the command line
  534. - if (cliArgs['js-flags']) {
  535. - jsFlags.push(cliArgs['js-flags']);
  536. - }
  537. -
  538. - if (process.platform === 'linux') {
  539. - // Fix cppgc crash on Linux with 16KB page size.
  540. - // Refs https://issues.chromium.org/issues/378017037
  541. - // The fix from https://github.com/electron/electron/commit/6c5b2ef55e08dc0bede02384747549c1eadac0eb
  542. - // only affects non-renderer process.
  543. - // The following will ensure that the flag will be
  544. - // applied to the renderer process as well.
  545. - // TODO(deepak1556): Remove this once we update to
  546. - // Chromium >= 134.
  547. - jsFlags.push('--nodecommit_pooled_pages');
  548. - }
  549. -
  550. - return jsFlags.length > 0 ? jsFlags.join(' ') : null;
  551. -}
  552. -
  553. -function parseCLIArgs(): NativeParsedArgs {
  554. - return minimist(process.argv, {
  555. - string: [
  556. - 'user-data-dir',
  557. - 'locale',
  558. - 'js-flags',
  559. - 'crash-reporter-directory'
  560. - ],
  561. - boolean: [
  562. - 'disable-chromium-sandbox',
  563. - ],
  564. - default: {
  565. - 'sandbox': true
  566. - },
  567. - alias: {
  568. - 'no-sandbox': 'sandbox'
  569. - }
  570. - });
  571. -}
  572. -
  573. -function registerListeners(): void {
  574. -
  575. - /**
  576. - * macOS: when someone drops a file to the not-yet running VSCode, the open-file event fires even before
  577. - * the app-ready event. We listen very early for open-file and remember this upon startup as path to open.
  578. - */
  579. - const macOpenFiles: string[] = [];
  580. - (globalThis as any)['macOpenFiles'] = macOpenFiles;
  581. - app.on('open-file', function (event, path) {
  582. - macOpenFiles.push(path);
  583. - });
  584. -
  585. - /**
  586. - * macOS: react to open-url requests.
  587. - */
  588. - const openUrls: string[] = [];
  589. - const onOpenUrl =
  590. - function (event: { preventDefault: () => void }, url: string) {
  591. - event.preventDefault();
  592. -
  593. - openUrls.push(url);
  594. - };
  595. -
  596. - app.on('will-finish-launching', function () {
  597. - app.on('open-url', onOpenUrl);
  598. - });
  599. -
  600. - (globalThis as any)['getOpenUrls'] = function () {
  601. - app.removeListener('open-url', onOpenUrl);
  602. -
  603. - return openUrls;
  604. - };
  605. -}
  606. -
  607. -function getCodeCachePath(): string | undefined {
  608. -
  609. - // explicitly disabled via CLI args
  610. - if (process.argv.indexOf('--no-cached-data') > 0) {
  611. - return undefined;
  612. - }
  613. -
  614. - // running out of sources
  615. - if (process.env['VSCODE_DEV']) {
  616. - return undefined;
  617. - }
  618. -
  619. - // require commit id
  620. - const commit = product.commit;
  621. - if (!commit) {
  622. - return undefined;
  623. - }
  624. -
  625. - return path.join(userDataPath, 'CachedData', commit);
  626. -}
  627. -
  628. -async function mkdirpIgnoreError(dir: string | undefined): Promise<string | undefined> {
  629. - if (typeof dir === 'string') {
  630. - try {
  631. - await fs.promises.mkdir(dir, { recursive: true });
  632. -
  633. - return dir;
  634. - } catch (error) {
  635. - // ignore
  636. - }
  637. - }
  638. -
  639. - return undefined;
  640. -}
  641. -
  642. -//#region NLS Support
  643. -
  644. -function processZhLocale(appLocale: string): string {
  645. - if (appLocale.startsWith('zh')) {
  646. - const region = appLocale.split('-')[1];
  647. -
  648. - // On Windows and macOS, Chinese languages returned by
  649. - // app.getPreferredSystemLanguages() start with zh-hans
  650. - // for Simplified Chinese or zh-hant for Traditional Chinese,
  651. - // so we can easily determine whether to use Simplified or Traditional.
  652. - // However, on Linux, Chinese languages returned by that same API
  653. - // are of the form zh-XY, where XY is a country code.
  654. - // For China (CN), Singapore (SG), and Malaysia (MY)
  655. - // country codes, assume they use Simplified Chinese.
  656. - // For other cases, assume they use Traditional.
  657. - if (['hans', 'cn', 'sg', 'my'].includes(region)) {
  658. - return 'zh-cn';
  659. - }
  660. -
  661. - return 'zh-tw';
  662. - }
  663. -
  664. - return appLocale;
  665. -}
  666. -
  667. -/**
  668. - * Resolve the NLS configuration
  669. - */
  670. -async function resolveNlsConfiguration(): Promise<INLSConfiguration> {
  671. -
  672. - // First, we need to test a user defined locale.
  673. - // If it fails we try the app locale.
  674. - // If that fails we fall back to English.
  675. -
  676. - const nlsConfiguration = nlsConfigurationPromise ? await nlsConfigurationPromise : undefined;
  677. - if (nlsConfiguration) {
  678. - return nlsConfiguration;
  679. - }
  680. -
  681. - // Try to use the app locale which is only valid
  682. - // after the app ready event has been fired.
  683. -
  684. - let userLocale = app.getLocale();
  685. - if (!userLocale) {
  686. - return {
  687. - userLocale: 'en',
  688. - osLocale,
  689. - resolvedLanguage: 'en',
  690. - defaultMessagesFile: path.join(__dirname, 'nls.messages.json'),
  691. -
  692. - // NLS: below 2 are a relic from old times only used by vscode-nls and deprecated
  693. - locale: 'en',
  694. - availableLanguages: {}
  695. - };
  696. - }
  697. -
  698. - // See above the comment about the loader and case sensitiveness
  699. - userLocale = processZhLocale(userLocale.toLowerCase());
  700. -
  701. - return resolveNLSConfiguration({
  702. - userLocale,
  703. - osLocale,
  704. - commit: product.commit,
  705. - userDataPath,
  706. - nlsMetadataPath: __dirname
  707. - });
  708. -}
  709. -
  710. -/**
  711. - * Language tags are case insensitive however an ESM loader is case sensitive
  712. - * To make this work on case preserving & insensitive FS we do the following:
  713. - * the language bundles have lower case language tags and we always lower case
  714. - * the locale we receive from the user or OS.
  715. - */
  716. -function getUserDefinedLocale(argvConfig: IArgvConfig): string | undefined {
  717. - const locale = args['locale'];
  718. - if (locale) {
  719. - return locale.toLowerCase(); // a directly provided --locale always wins
  720. - }
  721. -
  722. - return typeof argvConfig?.locale === 'string' ? argvConfig.locale.toLowerCase() : undefined;
  723. -}
  724. -
  725. -//#endregion
  726. diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts
  727. index 7227aba24f3..af3d09a5b2d 100644
  728. --- a/src/vs/base/browser/dom.ts
  729. +++ b/src/vs/base/browser/dom.ts
  730. @@ -3,28 +3,28 @@
  731. * Licensed under the MIT License. See License.txt in the project root for license information.
  732. *--------------------------------------------------------------------------------------------*/
  733. -import * as browser from './browser.js';
  734. -import { BrowserFeatures } from './canIUse.js';
  735. -import { IKeyboardEvent, StandardKeyboardEvent } from './keyboardEvent.js';
  736. -import { IMouseEvent, StandardMouseEvent } from './mouseEvent.js';
  737. -import { AbstractIdleValue, IntervalTimer, TimeoutTimer, _runWhenIdle, IdleDeadline } from '../common/async.js';
  738. -import { onUnexpectedError } from '../common/errors.js';
  739. -import * as event from '../common/event.js';
  740. -import dompurify from './dompurify/dompurify.js';
  741. -import { KeyCode } from '../common/keyCodes.js';
  742. -import { Disposable, DisposableStore, IDisposable, toDisposable } from '../common/lifecycle.js';
  743. -import { RemoteAuthorities, Schemas } from '../common/network.js';
  744. -import * as platform from '../common/platform.js';
  745. -import { URI } from '../common/uri.js';
  746. -import { hash } from '../common/hash.js';
  747. -import { CodeWindow, ensureCodeWindow, mainWindow } from './window.js';
  748. -import { isPointWithinTriangle } from '../common/numbers.js';
  749. -export * from './domImpl/domObservable.js';
  750. -export * from './domImpl/n.js';
  751. +import * as browser from "./browser.js"
  752. +import { BrowserFeatures } from "./canIUse.js"
  753. +import { IKeyboardEvent, StandardKeyboardEvent } from "./keyboardEvent.js"
  754. +import { IMouseEvent, StandardMouseEvent } from "./mouseEvent.js"
  755. +import { AbstractIdleValue, IntervalTimer, TimeoutTimer, _runWhenIdle, IdleDeadline } from "../common/async.js"
  756. +import { onUnexpectedError } from "../common/errors.js"
  757. +import * as event from "../common/event.js"
  758. +import dompurify from "./dompurify/dompurify.js"
  759. +import { KeyCode } from "../common/keyCodes.js"
  760. +import { Disposable, DisposableStore, IDisposable, toDisposable } from "../common/lifecycle.js"
  761. +import { RemoteAuthorities, Schemas } from "../common/network.js"
  762. +import * as platform from "../common/platform.js"
  763. +import { URI } from "../common/uri.js"
  764. +import { hash } from "../common/hash.js"
  765. +import { CodeWindow, ensureCodeWindow, mainWindow } from "./window.js"
  766. +import { isPointWithinTriangle } from "../common/numbers.js"
  767. +export * from "./domImpl/domObservable.js"
  768. +export * from "./domImpl/n.js"
  769. export interface IRegisteredCodeWindow {
  770. - readonly window: CodeWindow;
  771. - readonly disposables: DisposableStore;
  772. + readonly window: CodeWindow
  773. + readonly disposables: DisposableStore
  774. }
  775. //# region Multi-Window Support Utilities
  776. @@ -40,24 +40,24 @@ export const {
  777. hasWindow,
  778. onDidRegisterWindow,
  779. onWillUnregisterWindow,
  780. - onDidUnregisterWindow
  781. + onDidUnregisterWindow,
  782. } = (function () {
  783. - const windows = new Map<number, IRegisteredCodeWindow>();
  784. + const windows = new Map<number, IRegisteredCodeWindow>()
  785. - ensureCodeWindow(mainWindow, 1);
  786. - const mainWindowRegistration = { window: mainWindow, disposables: new DisposableStore() };
  787. - windows.set(mainWindow.vscodeWindowId, mainWindowRegistration);
  788. + ensureCodeWindow(mainWindow, 1)
  789. + const mainWindowRegistration = { window: mainWindow, disposables: new DisposableStore() }
  790. + windows.set(mainWindow.vscodeWindowId, mainWindowRegistration)
  791. - const onDidRegisterWindow = new event.Emitter<IRegisteredCodeWindow>();
  792. - const onDidUnregisterWindow = new event.Emitter<CodeWindow>();
  793. - const onWillUnregisterWindow = new event.Emitter<CodeWindow>();
  794. + const onDidRegisterWindow = new event.Emitter<IRegisteredCodeWindow>()
  795. + const onDidUnregisterWindow = new event.Emitter<CodeWindow>()
  796. + const onWillUnregisterWindow = new event.Emitter<CodeWindow>()
  797. - function getWindowById(windowId: number): IRegisteredCodeWindow | undefined;
  798. - function getWindowById(windowId: number | undefined, fallbackToMain: true): IRegisteredCodeWindow;
  799. + function getWindowById(windowId: number): IRegisteredCodeWindow | undefined
  800. + function getWindowById(windowId: number | undefined, fallbackToMain: true): IRegisteredCodeWindow
  801. function getWindowById(windowId: number | undefined, fallbackToMain?: boolean): IRegisteredCodeWindow | undefined {
  802. - const window = typeof windowId === 'number' ? windows.get(windowId) : undefined;
  803. + const window = typeof windowId === "number" ? windows.get(windowId) : undefined
  804. - return window ?? (fallbackToMain ? mainWindowRegistration : undefined);
  805. + return window ?? (fallbackToMain ? mainWindowRegistration : undefined)
  806. }
  807. return {
  808. @@ -66,161 +66,230 @@ export const {
  809. onDidUnregisterWindow: onDidUnregisterWindow.event,
  810. registerWindow(window: CodeWindow): IDisposable {
  811. if (windows.has(window.vscodeWindowId)) {
  812. - return Disposable.None;
  813. + return Disposable.None
  814. }
  815. - const disposables = new DisposableStore();
  816. + const disposables = new DisposableStore()
  817. const registeredWindow = {
  818. window,
  819. - disposables: disposables.add(new DisposableStore())
  820. - };
  821. - windows.set(window.vscodeWindowId, registeredWindow);
  822. + disposables: disposables.add(new DisposableStore()),
  823. + }
  824. + windows.set(window.vscodeWindowId, registeredWindow)
  825. - disposables.add(toDisposable(() => {
  826. - windows.delete(window.vscodeWindowId);
  827. - onDidUnregisterWindow.fire(window);
  828. - }));
  829. + disposables.add(
  830. + toDisposable(() => {
  831. + windows.delete(window.vscodeWindowId)
  832. + onDidUnregisterWindow.fire(window)
  833. + }),
  834. + )
  835. - disposables.add(addDisposableListener(window, EventType.BEFORE_UNLOAD, () => {
  836. - onWillUnregisterWindow.fire(window);
  837. - }));
  838. + disposables.add(
  839. + addDisposableListener(window, EventType.BEFORE_UNLOAD, () => {
  840. + onWillUnregisterWindow.fire(window)
  841. + }),
  842. + )
  843. - onDidRegisterWindow.fire(registeredWindow);
  844. + onDidRegisterWindow.fire(registeredWindow)
  845. - return disposables;
  846. + return disposables
  847. },
  848. getWindows(): Iterable<IRegisteredCodeWindow> {
  849. - return windows.values();
  850. + return windows.values()
  851. },
  852. getWindowsCount(): number {
  853. - return windows.size;
  854. + return windows.size
  855. },
  856. getWindowId(targetWindow: Window): number {
  857. - return (targetWindow as CodeWindow).vscodeWindowId;
  858. + return (targetWindow as CodeWindow).vscodeWindowId
  859. },
  860. hasWindow(windowId: number): boolean {
  861. - return windows.has(windowId);
  862. + return windows.has(windowId)
  863. },
  864. getWindowById,
  865. getWindow(e: Node | UIEvent | undefined | null): CodeWindow {
  866. - const candidateNode = e as Node | undefined | null;
  867. + const candidateNode = e as Node | undefined | null
  868. if (candidateNode?.ownerDocument?.defaultView) {
  869. - return candidateNode.ownerDocument.defaultView.window as CodeWindow;
  870. + return candidateNode.ownerDocument.defaultView.window as CodeWindow
  871. }
  872. - const candidateEvent = e as UIEvent | undefined | null;
  873. + const candidateEvent = e as UIEvent | undefined | null
  874. if (candidateEvent?.view) {
  875. - return candidateEvent.view.window as CodeWindow;
  876. + return candidateEvent.view.window as CodeWindow
  877. }
  878. - return mainWindow;
  879. + return mainWindow
  880. },
  881. getDocument(e: Node | UIEvent | undefined | null): Document {
  882. - const candidateNode = e as Node | undefined | null;
  883. - return getWindow(candidateNode).document;
  884. - }
  885. - };
  886. -})();
  887. + const candidateNode = e as Node | undefined | null
  888. + return getWindow(candidateNode).document
  889. + },
  890. + }
  891. +})()
  892. //#endregion
  893. export function clearNode(node: HTMLElement): void {
  894. while (node.firstChild) {
  895. - node.firstChild.remove();
  896. + node.firstChild.remove()
  897. }
  898. }
  899. class DomListener implements IDisposable {
  900. + private _handler: (e: any) => void
  901. + private _node: EventTarget
  902. + private readonly _type: string
  903. + private readonly _options: boolean | AddEventListenerOptions
  904. - private _handler: (e: any) => void;
  905. - private _node: EventTarget;
  906. - private readonly _type: string;
  907. - private readonly _options: boolean | AddEventListenerOptions;
  908. -
  909. - constructor(node: EventTarget, type: string, handler: (e: any) => void, options?: boolean | AddEventListenerOptions) {
  910. - this._node = node;
  911. - this._type = type;
  912. - this._handler = handler;
  913. - this._options = (options || false);
  914. - this._node.addEventListener(this._type, this._handler, this._options);
  915. + constructor(
  916. + node: EventTarget,
  917. + type: string,
  918. + handler: (e: any) => void,
  919. + options?: boolean | AddEventListenerOptions,
  920. + ) {
  921. + this._node = node
  922. + this._type = type
  923. + this._handler = handler
  924. + this._options = options || false
  925. + this._node.addEventListener(this._type, this._handler, this._options)
  926. }
  927. dispose(): void {
  928. if (!this._handler) {
  929. // Already disposed
  930. - return;
  931. + return
  932. }
  933. - this._node.removeEventListener(this._type, this._handler, this._options);
  934. + this._node.removeEventListener(this._type, this._handler, this._options)
  935. // Prevent leakers from holding on to the dom or handler func
  936. - this._node = null!;
  937. - this._handler = null!;
  938. - }
  939. -}
  940. -
  941. -export function addDisposableListener<K extends keyof GlobalEventHandlersEventMap>(node: EventTarget, type: K, handler: (event: GlobalEventHandlersEventMap[K]) => void, useCapture?: boolean): IDisposable;
  942. -export function addDisposableListener(node: EventTarget, type: string, handler: (event: any) => void, useCapture?: boolean): IDisposable;
  943. -export function addDisposableListener(node: EventTarget, type: string, handler: (event: any) => void, options: AddEventListenerOptions): IDisposable;
  944. -export function addDisposableListener(node: EventTarget, type: string, handler: (event: any) => void, useCaptureOrOptions?: boolean | AddEventListenerOptions): IDisposable {
  945. - return new DomListener(node, type, handler, useCaptureOrOptions);
  946. + this._node = null!
  947. + this._handler = null!
  948. + }
  949. +}
  950. +
  951. +export function addDisposableListener<K extends keyof GlobalEventHandlersEventMap>(
  952. + node: EventTarget,
  953. + type: K,
  954. + handler: (event: GlobalEventHandlersEventMap[K]) => void,
  955. + useCapture?: boolean,
  956. +): IDisposable
  957. +export function addDisposableListener(
  958. + node: EventTarget,
  959. + type: string,
  960. + handler: (event: any) => void,
  961. + useCapture?: boolean,
  962. +): IDisposable
  963. +export function addDisposableListener(
  964. + node: EventTarget,
  965. + type: string,
  966. + handler: (event: any) => void,
  967. + options: AddEventListenerOptions,
  968. +): IDisposable
  969. +export function addDisposableListener(
  970. + node: EventTarget,
  971. + type: string,
  972. + handler: (event: any) => void,
  973. + useCaptureOrOptions?: boolean | AddEventListenerOptions,
  974. +): IDisposable {
  975. + return new DomListener(node, type, handler, useCaptureOrOptions)
  976. }
  977. export interface IAddStandardDisposableListenerSignature {
  978. - (node: HTMLElement, type: 'click', handler: (event: IMouseEvent) => void, useCapture?: boolean): IDisposable;
  979. - (node: HTMLElement, type: 'mousedown', handler: (event: IMouseEvent) => void, useCapture?: boolean): IDisposable;
  980. - (node: HTMLElement, type: 'keydown', handler: (event: IKeyboardEvent) => void, useCapture?: boolean): IDisposable;
  981. - (node: HTMLElement, type: 'keypress', handler: (event: IKeyboardEvent) => void, useCapture?: boolean): IDisposable;
  982. - (node: HTMLElement, type: 'keyup', handler: (event: IKeyboardEvent) => void, useCapture?: boolean): IDisposable;
  983. - (node: HTMLElement, type: 'pointerdown', handler: (event: PointerEvent) => void, useCapture?: boolean): IDisposable;
  984. - (node: HTMLElement, type: 'pointermove', handler: (event: PointerEvent) => void, useCapture?: boolean): IDisposable;
  985. - (node: HTMLElement, type: 'pointerup', handler: (event: PointerEvent) => void, useCapture?: boolean): IDisposable;
  986. - (node: HTMLElement, type: string, handler: (event: any) => void, useCapture?: boolean): IDisposable;
  987. + (node: HTMLElement, type: "click", handler: (event: IMouseEvent) => void, useCapture?: boolean): IDisposable
  988. + (node: HTMLElement, type: "mousedown", handler: (event: IMouseEvent) => void, useCapture?: boolean): IDisposable
  989. + (node: HTMLElement, type: "keydown", handler: (event: IKeyboardEvent) => void, useCapture?: boolean): IDisposable
  990. + (node: HTMLElement, type: "keypress", handler: (event: IKeyboardEvent) => void, useCapture?: boolean): IDisposable
  991. + (node: HTMLElement, type: "keyup", handler: (event: IKeyboardEvent) => void, useCapture?: boolean): IDisposable
  992. + (node: HTMLElement, type: "pointerdown", handler: (event: PointerEvent) => void, useCapture?: boolean): IDisposable
  993. + (node: HTMLElement, type: "pointermove", handler: (event: PointerEvent) => void, useCapture?: boolean): IDisposable
  994. + (node: HTMLElement, type: "pointerup", handler: (event: PointerEvent) => void, useCapture?: boolean): IDisposable
  995. + (node: HTMLElement, type: string, handler: (event: any) => void, useCapture?: boolean): IDisposable
  996. }
  997. function _wrapAsStandardMouseEvent(targetWindow: Window, handler: (e: IMouseEvent) => void): (e: MouseEvent) => void {
  998. return function (e: MouseEvent) {
  999. - return handler(new StandardMouseEvent(targetWindow, e));
  1000. - };
  1001. + return handler(new StandardMouseEvent(targetWindow, e))
  1002. + }
  1003. }
  1004. function _wrapAsStandardKeyboardEvent(handler: (e: IKeyboardEvent) => void): (e: KeyboardEvent) => void {
  1005. return function (e: KeyboardEvent) {
  1006. - return handler(new StandardKeyboardEvent(e));
  1007. - };
  1008. -}
  1009. -export const addStandardDisposableListener: IAddStandardDisposableListenerSignature = function addStandardDisposableListener(node: HTMLElement, type: string, handler: (event: any) => void, useCapture?: boolean): IDisposable {
  1010. - let wrapHandler = handler;
  1011. -
  1012. - if (type === 'click' || type === 'mousedown' || type === 'contextmenu') {
  1013. - wrapHandler = _wrapAsStandardMouseEvent(getWindow(node), handler);
  1014. - } else if (type === 'keydown' || type === 'keypress' || type === 'keyup') {
  1015. - wrapHandler = _wrapAsStandardKeyboardEvent(handler);
  1016. - }
  1017. -
  1018. - return addDisposableListener(node, type, wrapHandler, useCapture);
  1019. -};
  1020. -
  1021. -export const addStandardDisposableGenericMouseDownListener = function addStandardDisposableListener(node: HTMLElement, handler: (event: any) => void, useCapture?: boolean): IDisposable {
  1022. - const wrapHandler = _wrapAsStandardMouseEvent(getWindow(node), handler);
  1023. -
  1024. - return addDisposableGenericMouseDownListener(node, wrapHandler, useCapture);
  1025. -};
  1026. -
  1027. -export const addStandardDisposableGenericMouseUpListener = function addStandardDisposableListener(node: HTMLElement, handler: (event: any) => void, useCapture?: boolean): IDisposable {
  1028. - const wrapHandler = _wrapAsStandardMouseEvent(getWindow(node), handler);
  1029. -
  1030. - return addDisposableGenericMouseUpListener(node, wrapHandler, useCapture);
  1031. -};
  1032. -export function addDisposableGenericMouseDownListener(node: EventTarget, handler: (event: any) => void, useCapture?: boolean): IDisposable {
  1033. - return addDisposableListener(node, platform.isIOS && BrowserFeatures.pointerEvents ? EventType.POINTER_DOWN : EventType.MOUSE_DOWN, handler, useCapture);
  1034. -}
  1035. -
  1036. -export function addDisposableGenericMouseMoveListener(node: EventTarget, handler: (event: any) => void, useCapture?: boolean): IDisposable {
  1037. - return addDisposableListener(node, platform.isIOS && BrowserFeatures.pointerEvents ? EventType.POINTER_MOVE : EventType.MOUSE_MOVE, handler, useCapture);
  1038. -}
  1039. + return handler(new StandardKeyboardEvent(e))
  1040. + }
  1041. +}
  1042. +export const addStandardDisposableListener: IAddStandardDisposableListenerSignature =
  1043. + function addStandardDisposableListener(
  1044. + node: HTMLElement,
  1045. + type: string,
  1046. + handler: (event: any) => void,
  1047. + useCapture?: boolean,
  1048. + ): IDisposable {
  1049. + let wrapHandler = handler
  1050. +
  1051. + if (type === "click" || type === "mousedown" || type === "contextmenu") {
  1052. + wrapHandler = _wrapAsStandardMouseEvent(getWindow(node), handler)
  1053. + } else if (type === "keydown" || type === "keypress" || type === "keyup") {
  1054. + wrapHandler = _wrapAsStandardKeyboardEvent(handler)
  1055. + }
  1056. -export function addDisposableGenericMouseUpListener(node: EventTarget, handler: (event: any) => void, useCapture?: boolean): IDisposable {
  1057. - return addDisposableListener(node, platform.isIOS && BrowserFeatures.pointerEvents ? EventType.POINTER_UP : EventType.MOUSE_UP, handler, useCapture);
  1058. + return addDisposableListener(node, type, wrapHandler, useCapture)
  1059. + }
  1060. +
  1061. +export const addStandardDisposableGenericMouseDownListener = function addStandardDisposableListener(
  1062. + node: HTMLElement,
  1063. + handler: (event: any) => void,
  1064. + useCapture?: boolean,
  1065. +): IDisposable {
  1066. + const wrapHandler = _wrapAsStandardMouseEvent(getWindow(node), handler)
  1067. +
  1068. + return addDisposableGenericMouseDownListener(node, wrapHandler, useCapture)
  1069. +}
  1070. +
  1071. +export const addStandardDisposableGenericMouseUpListener = function addStandardDisposableListener(
  1072. + node: HTMLElement,
  1073. + handler: (event: any) => void,
  1074. + useCapture?: boolean,
  1075. +): IDisposable {
  1076. + const wrapHandler = _wrapAsStandardMouseEvent(getWindow(node), handler)
  1077. +
  1078. + return addDisposableGenericMouseUpListener(node, wrapHandler, useCapture)
  1079. +}
  1080. +export function addDisposableGenericMouseDownListener(
  1081. + node: EventTarget,
  1082. + handler: (event: any) => void,
  1083. + useCapture?: boolean,
  1084. +): IDisposable {
  1085. + return addDisposableListener(
  1086. + node,
  1087. + platform.isIOS && BrowserFeatures.pointerEvents ? EventType.POINTER_DOWN : EventType.MOUSE_DOWN,
  1088. + handler,
  1089. + useCapture,
  1090. + )
  1091. +}
  1092. +
  1093. +export function addDisposableGenericMouseMoveListener(
  1094. + node: EventTarget,
  1095. + handler: (event: any) => void,
  1096. + useCapture?: boolean,
  1097. +): IDisposable {
  1098. + return addDisposableListener(
  1099. + node,
  1100. + platform.isIOS && BrowserFeatures.pointerEvents ? EventType.POINTER_MOVE : EventType.MOUSE_MOVE,
  1101. + handler,
  1102. + useCapture,
  1103. + )
  1104. +}
  1105. +
  1106. +export function addDisposableGenericMouseUpListener(
  1107. + node: EventTarget,
  1108. + handler: (event: any) => void,
  1109. + useCapture?: boolean,
  1110. +): IDisposable {
  1111. + return addDisposableListener(
  1112. + node,
  1113. + platform.isIOS && BrowserFeatures.pointerEvents ? EventType.POINTER_UP : EventType.MOUSE_UP,
  1114. + handler,
  1115. + useCapture,
  1116. + )
  1117. }
  1118. /**
  1119. @@ -242,8 +311,12 @@ export function addDisposableGenericMouseUpListener(node: EventTarget, handler:
  1120. * [requestIdleCallback]: https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback
  1121. * [setTimeout]: https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout
  1122. */
  1123. -export function runWhenWindowIdle(targetWindow: Window | typeof globalThis, callback: (idle: IdleDeadline) => void, timeout?: number): IDisposable {
  1124. - return _runWhenIdle(targetWindow, callback, timeout);
  1125. +export function runWhenWindowIdle(
  1126. + targetWindow: Window | typeof globalThis,
  1127. + callback: (idle: IdleDeadline) => void,
  1128. + timeout?: number,
  1129. +): IDisposable {
  1130. + return _runWhenIdle(targetWindow, callback, timeout)
  1131. }
  1132. /**
  1133. @@ -252,7 +325,7 @@ export function runWhenWindowIdle(targetWindow: Window | typeof globalThis, call
  1134. */
  1135. export class WindowIdleValue<T> extends AbstractIdleValue<T> {
  1136. constructor(targetWindow: Window | typeof globalThis, executor: () => T) {
  1137. - super(targetWindow, executor);
  1138. + super(targetWindow, executor)
  1139. }
  1140. }
  1141. @@ -262,299 +335,326 @@ export class WindowIdleValue<T> extends AbstractIdleValue<T> {
  1142. * If currently in an animation frame, `runner` will be executed immediately.
  1143. * @return token that can be used to cancel the scheduled runner (only if `runner` was not executed immediately).
  1144. */
  1145. -export let runAtThisOrScheduleAtNextAnimationFrame: (targetWindow: Window, runner: () => void, priority?: number) => IDisposable;
  1146. +export let runAtThisOrScheduleAtNextAnimationFrame: (
  1147. + targetWindow: Window,
  1148. + runner: () => void,
  1149. + priority?: number,
  1150. +) => IDisposable
  1151. /**
  1152. * Schedule a callback to be run at the next animation frame.
  1153. * This allows multiple parties to register callbacks that should run at the next animation frame.
  1154. * If currently in an animation frame, `runner` will be executed at the next animation frame.
  1155. * @return token that can be used to cancel the scheduled runner.
  1156. */
  1157. -export let scheduleAtNextAnimationFrame: (targetWindow: Window, runner: () => void, priority?: number) => IDisposable;
  1158. -
  1159. -export function disposableWindowInterval(targetWindow: Window, handler: () => void | boolean /* stop interval */ | Promise<unknown>, interval: number, iterations?: number): IDisposable {
  1160. - let iteration = 0;
  1161. +export let scheduleAtNextAnimationFrame: (targetWindow: Window, runner: () => void, priority?: number) => IDisposable
  1162. +
  1163. +export function disposableWindowInterval(
  1164. + targetWindow: Window,
  1165. + handler: () => void | boolean /* stop interval */ | Promise<unknown>,
  1166. + interval: number,
  1167. + iterations?: number,
  1168. +): IDisposable {
  1169. + let iteration = 0
  1170. const timer = targetWindow.setInterval(() => {
  1171. - iteration++;
  1172. - if ((typeof iterations === 'number' && iteration >= iterations) || handler() === true) {
  1173. - disposable.dispose();
  1174. + iteration++
  1175. + if ((typeof iterations === "number" && iteration >= iterations) || handler() === true) {
  1176. + disposable.dispose()
  1177. }
  1178. - }, interval);
  1179. + }, interval)
  1180. const disposable = toDisposable(() => {
  1181. - targetWindow.clearInterval(timer);
  1182. - });
  1183. - return disposable;
  1184. + targetWindow.clearInterval(timer)
  1185. + })
  1186. + return disposable
  1187. }
  1188. export class WindowIntervalTimer extends IntervalTimer {
  1189. -
  1190. - private readonly defaultTarget?: Window & typeof globalThis;
  1191. + private readonly defaultTarget?: Window & typeof globalThis
  1192. /**
  1193. *
  1194. * @param node The optional node from which the target window is determined
  1195. */
  1196. constructor(node?: Node) {
  1197. - super();
  1198. - this.defaultTarget = node && getWindow(node);
  1199. + super()
  1200. + this.defaultTarget = node && getWindow(node)
  1201. }
  1202. override cancelAndSet(runner: () => void, interval: number, targetWindow?: Window & typeof globalThis): void {
  1203. - return super.cancelAndSet(runner, interval, targetWindow ?? this.defaultTarget);
  1204. + return super.cancelAndSet(runner, interval, targetWindow ?? this.defaultTarget)
  1205. }
  1206. }
  1207. class AnimationFrameQueueItem implements IDisposable {
  1208. -
  1209. - private _runner: () => void;
  1210. - public priority: number;
  1211. - private _canceled: boolean;
  1212. + private _runner: () => void
  1213. + public priority: number
  1214. + private _canceled: boolean
  1215. constructor(runner: () => void, priority: number = 0) {
  1216. - this._runner = runner;
  1217. - this.priority = priority;
  1218. - this._canceled = false;
  1219. + this._runner = runner
  1220. + this.priority = priority
  1221. + this._canceled = false
  1222. }
  1223. dispose(): void {
  1224. - this._canceled = true;
  1225. + this._canceled = true
  1226. }
  1227. execute(): void {
  1228. if (this._canceled) {
  1229. - return;
  1230. + return
  1231. }
  1232. try {
  1233. - this._runner();
  1234. + this._runner()
  1235. } catch (e) {
  1236. - onUnexpectedError(e);
  1237. + onUnexpectedError(e)
  1238. }
  1239. }
  1240. // Sort by priority (largest to lowest)
  1241. static sort(a: AnimationFrameQueueItem, b: AnimationFrameQueueItem): number {
  1242. - return b.priority - a.priority;
  1243. + return b.priority - a.priority
  1244. }
  1245. }
  1246. -(function () {
  1247. +;(function () {
  1248. /**
  1249. * The runners scheduled at the next animation frame
  1250. */
  1251. - const NEXT_QUEUE = new Map<number /* window ID */, AnimationFrameQueueItem[]>();
  1252. + const NEXT_QUEUE = new Map<number /* window ID */, AnimationFrameQueueItem[]>()
  1253. /**
  1254. * The runners scheduled at the current animation frame
  1255. */
  1256. - const CURRENT_QUEUE = new Map<number /* window ID */, AnimationFrameQueueItem[]>();
  1257. + const CURRENT_QUEUE = new Map<number /* window ID */, AnimationFrameQueueItem[]>()
  1258. /**
  1259. * A flag to keep track if the native requestAnimationFrame was already called
  1260. */
  1261. - const animFrameRequested = new Map<number /* window ID */, boolean>();
  1262. + const animFrameRequested = new Map<number /* window ID */, boolean>()
  1263. /**
  1264. * A flag to indicate if currently handling a native requestAnimationFrame callback
  1265. */
  1266. - const inAnimationFrameRunner = new Map<number /* window ID */, boolean>();
  1267. + const inAnimationFrameRunner = new Map<number /* window ID */, boolean>()
  1268. const animationFrameRunner = (targetWindowId: number) => {
  1269. - animFrameRequested.set(targetWindowId, false);
  1270. + animFrameRequested.set(targetWindowId, false)
  1271. - const currentQueue = NEXT_QUEUE.get(targetWindowId) ?? [];
  1272. - CURRENT_QUEUE.set(targetWindowId, currentQueue);
  1273. - NEXT_QUEUE.set(targetWindowId, []);
  1274. + const currentQueue = NEXT_QUEUE.get(targetWindowId) ?? []
  1275. + CURRENT_QUEUE.set(targetWindowId, currentQueue)
  1276. + NEXT_QUEUE.set(targetWindowId, [])
  1277. - inAnimationFrameRunner.set(targetWindowId, true);
  1278. + inAnimationFrameRunner.set(targetWindowId, true)
  1279. while (currentQueue.length > 0) {
  1280. - currentQueue.sort(AnimationFrameQueueItem.sort);
  1281. - const top = currentQueue.shift()!;
  1282. - top.execute();
  1283. + currentQueue.sort(AnimationFrameQueueItem.sort)
  1284. + const top = currentQueue.shift()!
  1285. + top.execute()
  1286. }
  1287. - inAnimationFrameRunner.set(targetWindowId, false);
  1288. - };
  1289. + inAnimationFrameRunner.set(targetWindowId, false)
  1290. + }
  1291. scheduleAtNextAnimationFrame = (targetWindow: Window, runner: () => void, priority: number = 0) => {
  1292. - const targetWindowId = getWindowId(targetWindow);
  1293. - const item = new AnimationFrameQueueItem(runner, priority);
  1294. + const targetWindowId = getWindowId(targetWindow)
  1295. + const item = new AnimationFrameQueueItem(runner, priority)
  1296. - let nextQueue = NEXT_QUEUE.get(targetWindowId);
  1297. + let nextQueue = NEXT_QUEUE.get(targetWindowId)
  1298. if (!nextQueue) {
  1299. - nextQueue = [];
  1300. - NEXT_QUEUE.set(targetWindowId, nextQueue);
  1301. + nextQueue = []
  1302. + NEXT_QUEUE.set(targetWindowId, nextQueue)
  1303. }
  1304. - nextQueue.push(item);
  1305. + nextQueue.push(item)
  1306. if (!animFrameRequested.get(targetWindowId)) {
  1307. - animFrameRequested.set(targetWindowId, true);
  1308. - targetWindow.requestAnimationFrame(() => animationFrameRunner(targetWindowId));
  1309. + animFrameRequested.set(targetWindowId, true)
  1310. + targetWindow.requestAnimationFrame(() => animationFrameRunner(targetWindowId))
  1311. }
  1312. - return item;
  1313. - };
  1314. + return item
  1315. + }
  1316. runAtThisOrScheduleAtNextAnimationFrame = (targetWindow: Window, runner: () => void, priority?: number) => {
  1317. - const targetWindowId = getWindowId(targetWindow);
  1318. + const targetWindowId = getWindowId(targetWindow)
  1319. if (inAnimationFrameRunner.get(targetWindowId)) {
  1320. - const item = new AnimationFrameQueueItem(runner, priority);
  1321. - let currentQueue = CURRENT_QUEUE.get(targetWindowId);
  1322. + const item = new AnimationFrameQueueItem(runner, priority)
  1323. + let currentQueue = CURRENT_QUEUE.get(targetWindowId)
  1324. if (!currentQueue) {
  1325. - currentQueue = [];
  1326. - CURRENT_QUEUE.set(targetWindowId, currentQueue);
  1327. + currentQueue = []
  1328. + CURRENT_QUEUE.set(targetWindowId, currentQueue)
  1329. }
  1330. - currentQueue.push(item);
  1331. - return item;
  1332. + currentQueue.push(item)
  1333. + return item
  1334. } else {
  1335. - return scheduleAtNextAnimationFrame(targetWindow, runner, priority);
  1336. + return scheduleAtNextAnimationFrame(targetWindow, runner, priority)
  1337. }
  1338. - };
  1339. -})();
  1340. + }
  1341. +})()
  1342. export function measure(targetWindow: Window, callback: () => void): IDisposable {
  1343. - return scheduleAtNextAnimationFrame(targetWindow, callback, 10000 /* must be early */);
  1344. + return scheduleAtNextAnimationFrame(targetWindow, callback, 10000 /* must be early */)
  1345. }
  1346. export function modify(targetWindow: Window, callback: () => void): IDisposable {
  1347. - return scheduleAtNextAnimationFrame(targetWindow, callback, -10000 /* must be late */);
  1348. + return scheduleAtNextAnimationFrame(targetWindow, callback, -10000 /* must be late */)
  1349. }
  1350. /**
  1351. * Add a throttled listener. `handler` is fired at most every 8.33333ms or with the next animation frame (if browser supports it).
  1352. */
  1353. export interface IEventMerger<R, E> {
  1354. - (lastEvent: R | null, currentEvent: E): R;
  1355. + (lastEvent: R | null, currentEvent: E): R
  1356. }
  1357. -const MINIMUM_TIME_MS = 8;
  1358. +const MINIMUM_TIME_MS = 8
  1359. const DEFAULT_EVENT_MERGER: IEventMerger<Event, Event> = function (lastEvent: Event | null, currentEvent: Event) {
  1360. - return currentEvent;
  1361. -};
  1362. + return currentEvent
  1363. +}
  1364. class TimeoutThrottledDomListener<R, E extends Event> extends Disposable {
  1365. + constructor(
  1366. + node: any,
  1367. + type: string,
  1368. + handler: (event: R) => void,
  1369. + eventMerger: IEventMerger<R, E> = <any>DEFAULT_EVENT_MERGER,
  1370. + minimumTimeMs: number = MINIMUM_TIME_MS,
  1371. + ) {
  1372. + super()
  1373. - constructor(node: any, type: string, handler: (event: R) => void, eventMerger: IEventMerger<R, E> = <any>DEFAULT_EVENT_MERGER, minimumTimeMs: number = MINIMUM_TIME_MS) {
  1374. - super();
  1375. -
  1376. - let lastEvent: R | null = null;
  1377. - let lastHandlerTime = 0;
  1378. - const timeout = this._register(new TimeoutTimer());
  1379. + let lastEvent: R | null = null
  1380. + let lastHandlerTime = 0
  1381. + const timeout = this._register(new TimeoutTimer())
  1382. const invokeHandler = () => {
  1383. - lastHandlerTime = (new Date()).getTime();
  1384. - handler(<R>lastEvent);
  1385. - lastEvent = null;
  1386. - };
  1387. -
  1388. - this._register(addDisposableListener(node, type, (e) => {
  1389. + lastHandlerTime = new Date().getTime()
  1390. + handler(<R>lastEvent)
  1391. + lastEvent = null
  1392. + }
  1393. - lastEvent = eventMerger(lastEvent, e);
  1394. - const elapsedTime = (new Date()).getTime() - lastHandlerTime;
  1395. + this._register(
  1396. + addDisposableListener(node, type, (e) => {
  1397. + lastEvent = eventMerger(lastEvent, e)
  1398. + const elapsedTime = new Date().getTime() - lastHandlerTime
  1399. - if (elapsedTime >= minimumTimeMs) {
  1400. - timeout.cancel();
  1401. - invokeHandler();
  1402. - } else {
  1403. - timeout.setIfNotSet(invokeHandler, minimumTimeMs - elapsedTime);
  1404. - }
  1405. - }));
  1406. + if (elapsedTime >= minimumTimeMs) {
  1407. + timeout.cancel()
  1408. + invokeHandler()
  1409. + } else {
  1410. + timeout.setIfNotSet(invokeHandler, minimumTimeMs - elapsedTime)
  1411. + }
  1412. + }),
  1413. + )
  1414. }
  1415. }
  1416. -export function addDisposableThrottledListener<R, E extends Event = Event>(node: any, type: string, handler: (event: R) => void, eventMerger?: IEventMerger<R, E>, minimumTimeMs?: number): IDisposable {
  1417. - return new TimeoutThrottledDomListener<R, E>(node, type, handler, eventMerger, minimumTimeMs);
  1418. +export function addDisposableThrottledListener<R, E extends Event = Event>(
  1419. + node: any,
  1420. + type: string,
  1421. + handler: (event: R) => void,
  1422. + eventMerger?: IEventMerger<R, E>,
  1423. + minimumTimeMs?: number,
  1424. +): IDisposable {
  1425. + return new TimeoutThrottledDomListener<R, E>(node, type, handler, eventMerger, minimumTimeMs)
  1426. }
  1427. export function getComputedStyle(el: HTMLElement): CSSStyleDeclaration {
  1428. - return getWindow(el).getComputedStyle(el, null);
  1429. + return getWindow(el).getComputedStyle(el, null)
  1430. }
  1431. -export function getClientArea(element: HTMLElement, defaultValue?: Dimension, fallbackElement?: HTMLElement): Dimension {
  1432. - const elWindow = getWindow(element);
  1433. - const elDocument = elWindow.document;
  1434. +export function getClientArea(
  1435. + element: HTMLElement,
  1436. + defaultValue?: Dimension,
  1437. + fallbackElement?: HTMLElement,
  1438. +): Dimension {
  1439. + const elWindow = getWindow(element)
  1440. + const elDocument = elWindow.document
  1441. // Try with DOM clientWidth / clientHeight
  1442. if (element !== elDocument.body) {
  1443. - return new Dimension(element.clientWidth, element.clientHeight);
  1444. + return new Dimension(element.clientWidth, element.clientHeight)
  1445. }
  1446. // If visual view port exits and it's on mobile, it should be used instead of window innerWidth / innerHeight, or document.body.clientWidth / document.body.clientHeight
  1447. if (platform.isIOS && elWindow?.visualViewport) {
  1448. - return new Dimension(elWindow.visualViewport.width, elWindow.visualViewport.height);
  1449. + return new Dimension(elWindow.visualViewport.width, elWindow.visualViewport.height)
  1450. }
  1451. // Try innerWidth / innerHeight
  1452. if (elWindow?.innerWidth && elWindow.innerHeight) {
  1453. - return new Dimension(elWindow.innerWidth, elWindow.innerHeight);
  1454. + return new Dimension(elWindow.innerWidth, elWindow.innerHeight)
  1455. }
  1456. // Try with document.body.clientWidth / document.body.clientHeight
  1457. if (elDocument.body && elDocument.body.clientWidth && elDocument.body.clientHeight) {
  1458. - return new Dimension(elDocument.body.clientWidth, elDocument.body.clientHeight);
  1459. + return new Dimension(elDocument.body.clientWidth, elDocument.body.clientHeight)
  1460. }
  1461. // Try with document.documentElement.clientWidth / document.documentElement.clientHeight
  1462. - if (elDocument.documentElement && elDocument.documentElement.clientWidth && elDocument.documentElement.clientHeight) {
  1463. - return new Dimension(elDocument.documentElement.clientWidth, elDocument.documentElement.clientHeight);
  1464. + if (
  1465. + elDocument.documentElement &&
  1466. + elDocument.documentElement.clientWidth &&
  1467. + elDocument.documentElement.clientHeight
  1468. + ) {
  1469. + return new Dimension(elDocument.documentElement.clientWidth, elDocument.documentElement.clientHeight)
  1470. }
  1471. if (fallbackElement) {
  1472. - return getClientArea(fallbackElement, defaultValue);
  1473. + return getClientArea(fallbackElement, defaultValue)
  1474. }
  1475. if (defaultValue) {
  1476. - return defaultValue;
  1477. + return defaultValue
  1478. }
  1479. - throw new Error('Unable to figure out browser width and height');
  1480. + throw new Error("Unable to figure out browser width and height")
  1481. }
  1482. class SizeUtils {
  1483. // Adapted from WinJS
  1484. // Converts a CSS positioning string for the specified element to pixels.
  1485. private static convertToPixels(element: HTMLElement, value: string): number {
  1486. - return parseFloat(value) || 0;
  1487. + return parseFloat(value) || 0
  1488. }
  1489. private static getDimension(element: HTMLElement, cssPropertyName: string): number {
  1490. - const computedStyle = getComputedStyle(element);
  1491. - const value = computedStyle ? computedStyle.getPropertyValue(cssPropertyName) : '0';
  1492. - return SizeUtils.convertToPixels(element, value);
  1493. + const computedStyle = getComputedStyle(element)
  1494. + const value = computedStyle ? computedStyle.getPropertyValue(cssPropertyName) : "0"
  1495. + return SizeUtils.convertToPixels(element, value)
  1496. }
  1497. static getBorderLeftWidth(element: HTMLElement): number {
  1498. - return SizeUtils.getDimension(element, 'border-left-width');
  1499. + return SizeUtils.getDimension(element, "border-left-width")
  1500. }
  1501. static getBorderRightWidth(element: HTMLElement): number {
  1502. - return SizeUtils.getDimension(element, 'border-right-width');
  1503. + return SizeUtils.getDimension(element, "border-right-width")
  1504. }
  1505. static getBorderTopWidth(element: HTMLElement): number {
  1506. - return SizeUtils.getDimension(element, 'border-top-width');
  1507. + return SizeUtils.getDimension(element, "border-top-width")
  1508. }
  1509. static getBorderBottomWidth(element: HTMLElement): number {
  1510. - return SizeUtils.getDimension(element, 'border-bottom-width');
  1511. + return SizeUtils.getDimension(element, "border-bottom-width")
  1512. }
  1513. static getPaddingLeft(element: HTMLElement): number {
  1514. - return SizeUtils.getDimension(element, 'padding-left');
  1515. + return SizeUtils.getDimension(element, "padding-left")
  1516. }
  1517. static getPaddingRight(element: HTMLElement): number {
  1518. - return SizeUtils.getDimension(element, 'padding-right');
  1519. + return SizeUtils.getDimension(element, "padding-right")
  1520. }
  1521. static getPaddingTop(element: HTMLElement): number {
  1522. - return SizeUtils.getDimension(element, 'padding-top');
  1523. + return SizeUtils.getDimension(element, "padding-top")
  1524. }
  1525. static getPaddingBottom(element: HTMLElement): number {
  1526. - return SizeUtils.getDimension(element, 'padding-bottom');
  1527. + return SizeUtils.getDimension(element, "padding-bottom")
  1528. }
  1529. static getMarginLeft(element: HTMLElement): number {
  1530. - return SizeUtils.getDimension(element, 'margin-left');
  1531. + return SizeUtils.getDimension(element, "margin-left")
  1532. }
  1533. static getMarginTop(element: HTMLElement): number {
  1534. - return SizeUtils.getDimension(element, 'margin-top');
  1535. + return SizeUtils.getDimension(element, "margin-top")
  1536. }
  1537. static getMarginRight(element: HTMLElement): number {
  1538. - return SizeUtils.getDimension(element, 'margin-right');
  1539. + return SizeUtils.getDimension(element, "margin-right")
  1540. }
  1541. static getMarginBottom(element: HTMLElement): number {
  1542. - return SizeUtils.getDimension(element, 'margin-bottom');
  1543. + return SizeUtils.getDimension(element, "margin-bottom")
  1544. }
  1545. }
  1546. @@ -562,138 +662,148 @@ class SizeUtils {
  1547. // Position & Dimension
  1548. export interface IDimension {
  1549. - readonly width: number;
  1550. - readonly height: number;
  1551. + readonly width: number
  1552. + readonly height: number
  1553. }
  1554. export class Dimension implements IDimension {
  1555. -
  1556. - static readonly None = new Dimension(0, 0);
  1557. + static readonly None = new Dimension(0, 0)
  1558. constructor(
  1559. readonly width: number,
  1560. readonly height: number,
  1561. - ) { }
  1562. + ) {}
  1563. with(width: number = this.width, height: number = this.height): Dimension {
  1564. if (width !== this.width || height !== this.height) {
  1565. - return new Dimension(width, height);
  1566. + return new Dimension(width, height)
  1567. } else {
  1568. - return this;
  1569. + return this
  1570. }
  1571. }
  1572. static is(obj: unknown): obj is IDimension {
  1573. - return typeof obj === 'object' && typeof (<IDimension>obj).height === 'number' && typeof (<IDimension>obj).width === 'number';
  1574. + return (
  1575. + typeof obj === "object" &&
  1576. + typeof (<IDimension>obj).height === "number" &&
  1577. + typeof (<IDimension>obj).width === "number"
  1578. + )
  1579. }
  1580. static lift(obj: IDimension): Dimension {
  1581. if (obj instanceof Dimension) {
  1582. - return obj;
  1583. + return obj
  1584. } else {
  1585. - return new Dimension(obj.width, obj.height);
  1586. + return new Dimension(obj.width, obj.height)
  1587. }
  1588. }
  1589. static equals(a: Dimension | undefined, b: Dimension | undefined): boolean {
  1590. if (a === b) {
  1591. - return true;
  1592. + return true
  1593. }
  1594. if (!a || !b) {
  1595. - return false;
  1596. + return false
  1597. }
  1598. - return a.width === b.width && a.height === b.height;
  1599. + return a.width === b.width && a.height === b.height
  1600. }
  1601. }
  1602. export interface IDomPosition {
  1603. - readonly left: number;
  1604. - readonly top: number;
  1605. + readonly left: number
  1606. + readonly top: number
  1607. }
  1608. export function getTopLeftOffset(element: HTMLElement): IDomPosition {
  1609. // Adapted from WinJS.Utilities.getPosition
  1610. // and added borders to the mix
  1611. - let offsetParent = element.offsetParent;
  1612. - let top = element.offsetTop;
  1613. - let left = element.offsetLeft;
  1614. + let offsetParent = element.offsetParent
  1615. + let top = element.offsetTop
  1616. + let left = element.offsetLeft
  1617. while (
  1618. - (element = <HTMLElement>element.parentNode) !== null
  1619. - && element !== element.ownerDocument.body
  1620. - && element !== element.ownerDocument.documentElement
  1621. + (element = <HTMLElement>element.parentNode) !== null &&
  1622. + element !== element.ownerDocument.body &&
  1623. + element !== element.ownerDocument.documentElement
  1624. ) {
  1625. - top -= element.scrollTop;
  1626. - const c = isShadowRoot(element) ? null : getComputedStyle(element);
  1627. + top -= element.scrollTop
  1628. + const c = isShadowRoot(element) ? null : getComputedStyle(element)
  1629. if (c) {
  1630. - left -= c.direction !== 'rtl' ? element.scrollLeft : -element.scrollLeft;
  1631. + left -= c.direction !== "rtl" ? element.scrollLeft : -element.scrollLeft
  1632. }
  1633. if (element === offsetParent) {
  1634. - left += SizeUtils.getBorderLeftWidth(element);
  1635. - top += SizeUtils.getBorderTopWidth(element);
  1636. - top += element.offsetTop;
  1637. - left += element.offsetLeft;
  1638. - offsetParent = element.offsetParent;
  1639. + left += SizeUtils.getBorderLeftWidth(element)
  1640. + top += SizeUtils.getBorderTopWidth(element)
  1641. + top += element.offsetTop
  1642. + left += element.offsetLeft
  1643. + offsetParent = element.offsetParent
  1644. }
  1645. }
  1646. return {
  1647. left: left,
  1648. - top: top
  1649. - };
  1650. + top: top,
  1651. + }
  1652. }
  1653. export interface IDomNodePagePosition {
  1654. - left: number;
  1655. - top: number;
  1656. - width: number;
  1657. - height: number;
  1658. + left: number
  1659. + top: number
  1660. + width: number
  1661. + height: number
  1662. }
  1663. export function size(element: HTMLElement, width: number | null, height: number | null): void {
  1664. - if (typeof width === 'number') {
  1665. - element.style.width = `${width}px`;
  1666. + if (typeof width === "number") {
  1667. + element.style.width = `${width}px`
  1668. }
  1669. - if (typeof height === 'number') {
  1670. - element.style.height = `${height}px`;
  1671. + if (typeof height === "number") {
  1672. + element.style.height = `${height}px`
  1673. }
  1674. }
  1675. -export function position(element: HTMLElement, top: number, right?: number, bottom?: number, left?: number, position: string = 'absolute'): void {
  1676. - if (typeof top === 'number') {
  1677. - element.style.top = `${top}px`;
  1678. +export function position(
  1679. + element: HTMLElement,
  1680. + top: number,
  1681. + right?: number,
  1682. + bottom?: number,
  1683. + left?: number,
  1684. + position: string = "absolute",
  1685. +): void {
  1686. + if (typeof top === "number") {
  1687. + element.style.top = `${top}px`
  1688. }
  1689. - if (typeof right === 'number') {
  1690. - element.style.right = `${right}px`;
  1691. + if (typeof right === "number") {
  1692. + element.style.right = `${right}px`
  1693. }
  1694. - if (typeof bottom === 'number') {
  1695. - element.style.bottom = `${bottom}px`;
  1696. + if (typeof bottom === "number") {
  1697. + element.style.bottom = `${bottom}px`
  1698. }
  1699. - if (typeof left === 'number') {
  1700. - element.style.left = `${left}px`;
  1701. + if (typeof left === "number") {
  1702. + element.style.left = `${left}px`
  1703. }
  1704. - element.style.position = position;
  1705. + element.style.position = position
  1706. }
  1707. /**
  1708. * Returns the position of a dom node relative to the entire page.
  1709. */
  1710. export function getDomNodePagePosition(domNode: HTMLElement): IDomNodePagePosition {
  1711. - const bb = domNode.getBoundingClientRect();
  1712. - const window = getWindow(domNode);
  1713. + const bb = domNode.getBoundingClientRect()
  1714. + const window = getWindow(domNode)
  1715. return {
  1716. left: bb.left + window.scrollX,
  1717. top: bb.top + window.scrollY,
  1718. width: bb.width,
  1719. - height: bb.height
  1720. - };
  1721. + height: bb.height,
  1722. + }
  1723. }
  1724. /**
  1725. @@ -704,105 +814,104 @@ export function getDomNodePagePosition(domNode: HTMLElement): IDomNodePagePositi
  1726. * @returns true if the element is in the bottom right quarter of the container
  1727. */
  1728. export function isElementInBottomRightQuarter(element: HTMLElement, container: HTMLElement): boolean {
  1729. - const position = getDomNodePagePosition(element);
  1730. - const clientArea = getClientArea(container);
  1731. + const position = getDomNodePagePosition(element)
  1732. + const clientArea = getClientArea(container)
  1733. - return position.left > clientArea.width / 2 && position.top > clientArea.height / 2;
  1734. + return position.left > clientArea.width / 2 && position.top > clientArea.height / 2
  1735. }
  1736. /**
  1737. * Returns the effective zoom on a given element before window zoom level is applied
  1738. */
  1739. export function getDomNodeZoomLevel(domNode: HTMLElement): number {
  1740. - let testElement: HTMLElement | null = domNode;
  1741. - let zoom = 1.0;
  1742. + let testElement: HTMLElement | null = domNode
  1743. + let zoom = 1.0
  1744. do {
  1745. - const elementZoomLevel = (getComputedStyle(testElement) as any).zoom;
  1746. - if (elementZoomLevel !== null && elementZoomLevel !== undefined && elementZoomLevel !== '1') {
  1747. - zoom *= elementZoomLevel;
  1748. + const elementZoomLevel = (getComputedStyle(testElement) as any).zoom
  1749. + if (elementZoomLevel !== null && elementZoomLevel !== undefined && elementZoomLevel !== "1") {
  1750. + zoom *= elementZoomLevel
  1751. }
  1752. - testElement = testElement.parentElement;
  1753. - } while (testElement !== null && testElement !== testElement.ownerDocument.documentElement);
  1754. + testElement = testElement.parentElement
  1755. + } while (testElement !== null && testElement !== testElement.ownerDocument.documentElement)
  1756. - return zoom;
  1757. + return zoom
  1758. }
  1759. -
  1760. // Adapted from WinJS
  1761. // Gets the width of the element, including margins.
  1762. export function getTotalWidth(element: HTMLElement): number {
  1763. - const margin = SizeUtils.getMarginLeft(element) + SizeUtils.getMarginRight(element);
  1764. - return element.offsetWidth + margin;
  1765. + const margin = SizeUtils.getMarginLeft(element) + SizeUtils.getMarginRight(element)
  1766. + return element.offsetWidth + margin
  1767. }
  1768. export function getContentWidth(element: HTMLElement): number {
  1769. - const border = SizeUtils.getBorderLeftWidth(element) + SizeUtils.getBorderRightWidth(element);
  1770. - const padding = SizeUtils.getPaddingLeft(element) + SizeUtils.getPaddingRight(element);
  1771. - return element.offsetWidth - border - padding;
  1772. + const border = SizeUtils.getBorderLeftWidth(element) + SizeUtils.getBorderRightWidth(element)
  1773. + const padding = SizeUtils.getPaddingLeft(element) + SizeUtils.getPaddingRight(element)
  1774. + return element.offsetWidth - border - padding
  1775. }
  1776. export function getTotalScrollWidth(element: HTMLElement): number {
  1777. - const margin = SizeUtils.getMarginLeft(element) + SizeUtils.getMarginRight(element);
  1778. - return element.scrollWidth + margin;
  1779. + const margin = SizeUtils.getMarginLeft(element) + SizeUtils.getMarginRight(element)
  1780. + return element.scrollWidth + margin
  1781. }
  1782. // Adapted from WinJS
  1783. // Gets the height of the content of the specified element. The content height does not include borders or padding.
  1784. export function getContentHeight(element: HTMLElement): number {
  1785. - const border = SizeUtils.getBorderTopWidth(element) + SizeUtils.getBorderBottomWidth(element);
  1786. - const padding = SizeUtils.getPaddingTop(element) + SizeUtils.getPaddingBottom(element);
  1787. - return element.offsetHeight - border - padding;
  1788. + const border = SizeUtils.getBorderTopWidth(element) + SizeUtils.getBorderBottomWidth(element)
  1789. + const padding = SizeUtils.getPaddingTop(element) + SizeUtils.getPaddingBottom(element)
  1790. + return element.offsetHeight - border - padding
  1791. }
  1792. // Adapted from WinJS
  1793. // Gets the height of the element, including its margins.
  1794. export function getTotalHeight(element: HTMLElement): number {
  1795. - const margin = SizeUtils.getMarginTop(element) + SizeUtils.getMarginBottom(element);
  1796. - return element.offsetHeight + margin;
  1797. + const margin = SizeUtils.getMarginTop(element) + SizeUtils.getMarginBottom(element)
  1798. + return element.offsetHeight + margin
  1799. }
  1800. // Gets the left coordinate of the specified element relative to the specified parent.
  1801. function getRelativeLeft(element: HTMLElement, parent: HTMLElement): number {
  1802. if (element === null) {
  1803. - return 0;
  1804. + return 0
  1805. }
  1806. - const elementPosition = getTopLeftOffset(element);
  1807. - const parentPosition = getTopLeftOffset(parent);
  1808. - return elementPosition.left - parentPosition.left;
  1809. + const elementPosition = getTopLeftOffset(element)
  1810. + const parentPosition = getTopLeftOffset(parent)
  1811. + return elementPosition.left - parentPosition.left
  1812. }
  1813. export function getLargestChildWidth(parent: HTMLElement, children: HTMLElement[]): number {
  1814. const childWidths = children.map((child) => {
  1815. - return Math.max(getTotalScrollWidth(child), getTotalWidth(child)) + getRelativeLeft(child, parent) || 0;
  1816. - });
  1817. - const maxWidth = Math.max(...childWidths);
  1818. - return maxWidth;
  1819. + return Math.max(getTotalScrollWidth(child), getTotalWidth(child)) + getRelativeLeft(child, parent) || 0
  1820. + })
  1821. + const maxWidth = Math.max(...childWidths)
  1822. + return maxWidth
  1823. }
  1824. // ----------------------------------------------------------------------------------------
  1825. export function isAncestor(testChild: Node | null, testAncestor: Node | null): boolean {
  1826. - return Boolean(testAncestor?.contains(testChild));
  1827. + return Boolean(testAncestor?.contains(testChild))
  1828. }
  1829. -const parentFlowToDataKey = 'parentFlowToElementId';
  1830. +const parentFlowToDataKey = "parentFlowToElementId"
  1831. /**
  1832. * Set an explicit parent to use for nodes that are not part of the
  1833. * regular dom structure.
  1834. */
  1835. export function setParentFlowTo(fromChildElement: HTMLElement, toParentElement: Element): void {
  1836. - fromChildElement.dataset[parentFlowToDataKey] = toParentElement.id;
  1837. + fromChildElement.dataset[parentFlowToDataKey] = toParentElement.id
  1838. }
  1839. function getParentFlowToElement(node: HTMLElement): HTMLElement | null {
  1840. - const flowToParentId = node.dataset[parentFlowToDataKey];
  1841. - if (typeof flowToParentId === 'string') {
  1842. - return node.ownerDocument.getElementById(flowToParentId);
  1843. + const flowToParentId = node.dataset[parentFlowToDataKey]
  1844. + if (typeof flowToParentId === "string") {
  1845. + return node.ownerDocument.getElementById(flowToParentId)
  1846. }
  1847. - return null;
  1848. + return null
  1849. }
  1850. /**
  1851. @@ -810,72 +919,78 @@ function getParentFlowToElement(node: HTMLElement): HTMLElement | null {
  1852. * parents set by `setParentFlowTo`.
  1853. */
  1854. export function isAncestorUsingFlowTo(testChild: Node, testAncestor: Node): boolean {
  1855. - let node: Node | null = testChild;
  1856. + let node: Node | null = testChild
  1857. while (node) {
  1858. if (node === testAncestor) {
  1859. - return true;
  1860. + return true
  1861. }
  1862. if (isHTMLElement(node)) {
  1863. - const flowToParentElement = getParentFlowToElement(node);
  1864. + const flowToParentElement = getParentFlowToElement(node)
  1865. if (flowToParentElement) {
  1866. - node = flowToParentElement;
  1867. - continue;
  1868. + node = flowToParentElement
  1869. + continue
  1870. }
  1871. }
  1872. - node = node.parentNode;
  1873. + node = node.parentNode
  1874. }
  1875. - return false;
  1876. + return false
  1877. }
  1878. -export function findParentWithClass(node: HTMLElement, clazz: string, stopAtClazzOrNode?: string | HTMLElement): HTMLElement | null {
  1879. +export function findParentWithClass(
  1880. + node: HTMLElement,
  1881. + clazz: string,
  1882. + stopAtClazzOrNode?: string | HTMLElement,
  1883. +): HTMLElement | null {
  1884. while (node && node.nodeType === node.ELEMENT_NODE) {
  1885. if (node.classList.contains(clazz)) {
  1886. - return node;
  1887. + return node
  1888. }
  1889. if (stopAtClazzOrNode) {
  1890. - if (typeof stopAtClazzOrNode === 'string') {
  1891. + if (typeof stopAtClazzOrNode === "string") {
  1892. if (node.classList.contains(stopAtClazzOrNode)) {
  1893. - return null;
  1894. + return null
  1895. }
  1896. } else {
  1897. if (node === stopAtClazzOrNode) {
  1898. - return null;
  1899. + return null
  1900. }
  1901. }
  1902. }
  1903. - node = <HTMLElement>node.parentNode;
  1904. + node = <HTMLElement>node.parentNode
  1905. }
  1906. - return null;
  1907. + return null
  1908. }
  1909. -export function hasParentWithClass(node: HTMLElement, clazz: string, stopAtClazzOrNode?: string | HTMLElement): boolean {
  1910. - return !!findParentWithClass(node, clazz, stopAtClazzOrNode);
  1911. +export function hasParentWithClass(
  1912. + node: HTMLElement,
  1913. + clazz: string,
  1914. + stopAtClazzOrNode?: string | HTMLElement,
  1915. +): boolean {
  1916. + return !!findParentWithClass(node, clazz, stopAtClazzOrNode)
  1917. }
  1918. export function isShadowRoot(node: Node): node is ShadowRoot {
  1919. - return (
  1920. - node && !!(<ShadowRoot>node).host && !!(<ShadowRoot>node).mode
  1921. - );
  1922. + return node && !!(<ShadowRoot>node).host && !!(<ShadowRoot>node).mode
  1923. }
  1924. export function isInShadowDOM(domNode: Node): boolean {
  1925. - return !!getShadowRoot(domNode);
  1926. + return !!getShadowRoot(domNode)
  1927. }
  1928. export function getShadowRoot(domNode: Node): ShadowRoot | null {
  1929. while (domNode.parentNode) {
  1930. if (domNode === domNode.ownerDocument?.body) {
  1931. // reached the body
  1932. - return null;
  1933. + return null
  1934. }
  1935. - domNode = domNode.parentNode;
  1936. + domNode = domNode.parentNode
  1937. }
  1938. - return isShadowRoot(domNode) ? domNode : null;
  1939. + return isShadowRoot(domNode) ? domNode : null
  1940. }
  1941. /**
  1942. @@ -884,13 +999,13 @@ export function getShadowRoot(domNode: Node): ShadowRoot | null {
  1943. * window if no window has focus.
  1944. */
  1945. export function getActiveElement(): Element | null {
  1946. - let result = getActiveDocument().activeElement;
  1947. + let result = getActiveDocument().activeElement
  1948. while (result?.shadowRoot) {
  1949. - result = result.shadowRoot.activeElement;
  1950. + result = result.shadowRoot.activeElement
  1951. }
  1952. - return result;
  1953. + return result
  1954. }
  1955. /**
  1956. @@ -899,7 +1014,7 @@ export function getActiveElement(): Element | null {
  1957. * window has focus.
  1958. */
  1959. export function isActiveElement(element: Element): boolean {
  1960. - return getActiveElement() === element;
  1961. + return getActiveElement() === element
  1962. }
  1963. /**
  1964. @@ -907,7 +1022,7 @@ export function isActiveElement(element: Element): boolean {
  1965. * `ancestor`. Falls back to the main window if no window has focus.
  1966. */
  1967. export function isAncestorOfActiveElement(ancestor: Element): boolean {
  1968. - return isAncestor(getActiveElement(), ancestor);
  1969. + return isAncestor(getActiveElement(), ancestor)
  1970. }
  1971. /**
  1972. @@ -915,7 +1030,7 @@ export function isAncestorOfActiveElement(ancestor: Element): boolean {
  1973. * document has focus or will be the main windows document.
  1974. */
  1975. export function isActiveDocument(element: Element): boolean {
  1976. - return element.ownerDocument === getActiveDocument();
  1977. + return element.ownerDocument === getActiveDocument()
  1978. }
  1979. /**
  1980. @@ -925,11 +1040,11 @@ export function isActiveDocument(element: Element): boolean {
  1981. */
  1982. export function getActiveDocument(): Document {
  1983. if (getWindowsCount() <= 1) {
  1984. - return mainWindow.document;
  1985. + return mainWindow.document
  1986. }
  1987. - const documents = Array.from(getWindows()).map(({ window }) => window.document);
  1988. - return documents.find(doc => doc.hasFocus()) ?? mainWindow.document;
  1989. + const documents = Array.from(getWindows()).map(({ window }) => window.document)
  1990. + return documents.find((doc) => doc.hasFocus()) ?? mainWindow.document
  1991. }
  1992. /**
  1993. @@ -938,313 +1053,316 @@ export function getActiveDocument(): Document {
  1994. * the main window.
  1995. */
  1996. export function getActiveWindow(): CodeWindow {
  1997. - const document = getActiveDocument();
  1998. - return (document.defaultView?.window ?? mainWindow) as CodeWindow;
  1999. + const document = getActiveDocument()
  2000. + return (document.defaultView?.window ?? mainWindow) as CodeWindow
  2001. }
  2002. interface IMutationObserver {
  2003. - users: number;
  2004. - readonly observer: MutationObserver;
  2005. - readonly onDidMutate: event.Event<MutationRecord[]>;
  2006. + users: number
  2007. + readonly observer: MutationObserver
  2008. + readonly onDidMutate: event.Event<MutationRecord[]>
  2009. }
  2010. -export const sharedMutationObserver = new class {
  2011. -
  2012. - readonly mutationObservers = new Map<Node, Map<number, IMutationObserver>>();
  2013. +export const sharedMutationObserver = new (class {
  2014. + readonly mutationObservers = new Map<Node, Map<number, IMutationObserver>>()
  2015. observe(target: Node, disposables: DisposableStore, options?: MutationObserverInit): event.Event<MutationRecord[]> {
  2016. - let mutationObserversPerTarget = this.mutationObservers.get(target);
  2017. + let mutationObserversPerTarget = this.mutationObservers.get(target)
  2018. if (!mutationObserversPerTarget) {
  2019. - mutationObserversPerTarget = new Map<number, IMutationObserver>();
  2020. - this.mutationObservers.set(target, mutationObserversPerTarget);
  2021. + mutationObserversPerTarget = new Map<number, IMutationObserver>()
  2022. + this.mutationObservers.set(target, mutationObserversPerTarget)
  2023. }
  2024. - const optionsHash = hash(options);
  2025. - let mutationObserverPerOptions = mutationObserversPerTarget.get(optionsHash);
  2026. + const optionsHash = hash(options)
  2027. + let mutationObserverPerOptions = mutationObserversPerTarget.get(optionsHash)
  2028. if (!mutationObserverPerOptions) {
  2029. - const onDidMutate = new event.Emitter<MutationRecord[]>();
  2030. - const observer = new MutationObserver(mutations => onDidMutate.fire(mutations));
  2031. - observer.observe(target, options);
  2032. + const onDidMutate = new event.Emitter<MutationRecord[]>()
  2033. + const observer = new MutationObserver((mutations) => onDidMutate.fire(mutations))
  2034. + observer.observe(target, options)
  2035. - const resolvedMutationObserverPerOptions = mutationObserverPerOptions = {
  2036. + const resolvedMutationObserverPerOptions = (mutationObserverPerOptions = {
  2037. users: 1,
  2038. observer,
  2039. - onDidMutate: onDidMutate.event
  2040. - };
  2041. + onDidMutate: onDidMutate.event,
  2042. + })
  2043. - disposables.add(toDisposable(() => {
  2044. - resolvedMutationObserverPerOptions.users -= 1;
  2045. + disposables.add(
  2046. + toDisposable(() => {
  2047. + resolvedMutationObserverPerOptions.users -= 1
  2048. - if (resolvedMutationObserverPerOptions.users === 0) {
  2049. - onDidMutate.dispose();
  2050. - observer.disconnect();
  2051. + if (resolvedMutationObserverPerOptions.users === 0) {
  2052. + onDidMutate.dispose()
  2053. + observer.disconnect()
  2054. - mutationObserversPerTarget?.delete(optionsHash);
  2055. - if (mutationObserversPerTarget?.size === 0) {
  2056. - this.mutationObservers.delete(target);
  2057. + mutationObserversPerTarget?.delete(optionsHash)
  2058. + if (mutationObserversPerTarget?.size === 0) {
  2059. + this.mutationObservers.delete(target)
  2060. + }
  2061. }
  2062. - }
  2063. - }));
  2064. + }),
  2065. + )
  2066. - mutationObserversPerTarget.set(optionsHash, mutationObserverPerOptions);
  2067. + mutationObserversPerTarget.set(optionsHash, mutationObserverPerOptions)
  2068. } else {
  2069. - mutationObserverPerOptions.users += 1;
  2070. + mutationObserverPerOptions.users += 1
  2071. }
  2072. - return mutationObserverPerOptions.onDidMutate;
  2073. + return mutationObserverPerOptions.onDidMutate
  2074. }
  2075. -};
  2076. +})()
  2077. export function createMetaElement(container: HTMLElement = mainWindow.document.head): HTMLMetaElement {
  2078. - return createHeadElement('meta', container) as HTMLMetaElement;
  2079. + return createHeadElement("meta", container) as HTMLMetaElement
  2080. }
  2081. export function createLinkElement(container: HTMLElement = mainWindow.document.head): HTMLLinkElement {
  2082. - return createHeadElement('link', container) as HTMLLinkElement;
  2083. + return createHeadElement("link", container) as HTMLLinkElement
  2084. }
  2085. function createHeadElement(tagName: string, container: HTMLElement = mainWindow.document.head): HTMLElement {
  2086. - const element = document.createElement(tagName);
  2087. - container.appendChild(element);
  2088. - return element;
  2089. + const element = document.createElement(tagName)
  2090. + container.appendChild(element)
  2091. + return element
  2092. }
  2093. export function isHTMLElement(e: unknown): e is HTMLElement {
  2094. // eslint-disable-next-line no-restricted-syntax
  2095. - return e instanceof HTMLElement || e instanceof getWindow(e as Node).HTMLElement;
  2096. + return e instanceof HTMLElement || e instanceof getWindow(e as Node).HTMLElement
  2097. }
  2098. export function isHTMLAnchorElement(e: unknown): e is HTMLAnchorElement {
  2099. // eslint-disable-next-line no-restricted-syntax
  2100. - return e instanceof HTMLAnchorElement || e instanceof getWindow(e as Node).HTMLAnchorElement;
  2101. + return e instanceof HTMLAnchorElement || e instanceof getWindow(e as Node).HTMLAnchorElement
  2102. }
  2103. export function isHTMLSpanElement(e: unknown): e is HTMLSpanElement {
  2104. // eslint-disable-next-line no-restricted-syntax
  2105. - return e instanceof HTMLSpanElement || e instanceof getWindow(e as Node).HTMLSpanElement;
  2106. + return e instanceof HTMLSpanElement || e instanceof getWindow(e as Node).HTMLSpanElement
  2107. }
  2108. export function isHTMLTextAreaElement(e: unknown): e is HTMLTextAreaElement {
  2109. // eslint-disable-next-line no-restricted-syntax
  2110. - return e instanceof HTMLTextAreaElement || e instanceof getWindow(e as Node).HTMLTextAreaElement;
  2111. + return e instanceof HTMLTextAreaElement || e instanceof getWindow(e as Node).HTMLTextAreaElement
  2112. }
  2113. export function isHTMLInputElement(e: unknown): e is HTMLInputElement {
  2114. // eslint-disable-next-line no-restricted-syntax
  2115. - return e instanceof HTMLInputElement || e instanceof getWindow(e as Node).HTMLInputElement;
  2116. + return e instanceof HTMLInputElement || e instanceof getWindow(e as Node).HTMLInputElement
  2117. }
  2118. export function isHTMLButtonElement(e: unknown): e is HTMLButtonElement {
  2119. // eslint-disable-next-line no-restricted-syntax
  2120. - return e instanceof HTMLButtonElement || e instanceof getWindow(e as Node).HTMLButtonElement;
  2121. + return e instanceof HTMLButtonElement || e instanceof getWindow(e as Node).HTMLButtonElement
  2122. }
  2123. export function isHTMLDivElement(e: unknown): e is HTMLDivElement {
  2124. // eslint-disable-next-line no-restricted-syntax
  2125. - return e instanceof HTMLDivElement || e instanceof getWindow(e as Node).HTMLDivElement;
  2126. + return e instanceof HTMLDivElement || e instanceof getWindow(e as Node).HTMLDivElement
  2127. }
  2128. export function isSVGElement(e: unknown): e is SVGElement {
  2129. // eslint-disable-next-line no-restricted-syntax
  2130. - return e instanceof SVGElement || e instanceof getWindow(e as Node).SVGElement;
  2131. + return e instanceof SVGElement || e instanceof getWindow(e as Node).SVGElement
  2132. }
  2133. export function isMouseEvent(e: unknown): e is MouseEvent {
  2134. // eslint-disable-next-line no-restricted-syntax
  2135. - return e instanceof MouseEvent || e instanceof getWindow(e as UIEvent).MouseEvent;
  2136. + return e instanceof MouseEvent || e instanceof getWindow(e as UIEvent).MouseEvent
  2137. }
  2138. export function isKeyboardEvent(e: unknown): e is KeyboardEvent {
  2139. // eslint-disable-next-line no-restricted-syntax
  2140. - return e instanceof KeyboardEvent || e instanceof getWindow(e as UIEvent).KeyboardEvent;
  2141. + return e instanceof KeyboardEvent || e instanceof getWindow(e as UIEvent).KeyboardEvent
  2142. }
  2143. export function isPointerEvent(e: unknown): e is PointerEvent {
  2144. // eslint-disable-next-line no-restricted-syntax
  2145. - return e instanceof PointerEvent || e instanceof getWindow(e as UIEvent).PointerEvent;
  2146. + return e instanceof PointerEvent || e instanceof getWindow(e as UIEvent).PointerEvent
  2147. }
  2148. export function isDragEvent(e: unknown): e is DragEvent {
  2149. // eslint-disable-next-line no-restricted-syntax
  2150. - return e instanceof DragEvent || e instanceof getWindow(e as UIEvent).DragEvent;
  2151. + return e instanceof DragEvent || e instanceof getWindow(e as UIEvent).DragEvent
  2152. }
  2153. export const EventType = {
  2154. // Mouse
  2155. - CLICK: 'click',
  2156. - AUXCLICK: 'auxclick',
  2157. - DBLCLICK: 'dblclick',
  2158. - MOUSE_UP: 'mouseup',
  2159. - MOUSE_DOWN: 'mousedown',
  2160. - MOUSE_OVER: 'mouseover',
  2161. - MOUSE_MOVE: 'mousemove',
  2162. - MOUSE_OUT: 'mouseout',
  2163. - MOUSE_ENTER: 'mouseenter',
  2164. - MOUSE_LEAVE: 'mouseleave',
  2165. - MOUSE_WHEEL: 'wheel',
  2166. - POINTER_UP: 'pointerup',
  2167. - POINTER_DOWN: 'pointerdown',
  2168. - POINTER_MOVE: 'pointermove',
  2169. - POINTER_LEAVE: 'pointerleave',
  2170. - CONTEXT_MENU: 'contextmenu',
  2171. - WHEEL: 'wheel',
  2172. + CLICK: "click",
  2173. + AUXCLICK: "auxclick",
  2174. + DBLCLICK: "dblclick",
  2175. + MOUSE_UP: "mouseup",
  2176. + MOUSE_DOWN: "mousedown",
  2177. + MOUSE_OVER: "mouseover",
  2178. + MOUSE_MOVE: "mousemove",
  2179. + MOUSE_OUT: "mouseout",
  2180. + MOUSE_ENTER: "mouseenter",
  2181. + MOUSE_LEAVE: "mouseleave",
  2182. + MOUSE_WHEEL: "wheel",
  2183. + POINTER_UP: "pointerup",
  2184. + POINTER_DOWN: "pointerdown",
  2185. + POINTER_MOVE: "pointermove",
  2186. + POINTER_LEAVE: "pointerleave",
  2187. + CONTEXT_MENU: "contextmenu",
  2188. + WHEEL: "wheel",
  2189. // Keyboard
  2190. - KEY_DOWN: 'keydown',
  2191. - KEY_PRESS: 'keypress',
  2192. - KEY_UP: 'keyup',
  2193. + KEY_DOWN: "keydown",
  2194. + KEY_PRESS: "keypress",
  2195. + KEY_UP: "keyup",
  2196. // HTML Document
  2197. - LOAD: 'load',
  2198. - BEFORE_UNLOAD: 'beforeunload',
  2199. - UNLOAD: 'unload',
  2200. - PAGE_SHOW: 'pageshow',
  2201. - PAGE_HIDE: 'pagehide',
  2202. - PASTE: 'paste',
  2203. - ABORT: 'abort',
  2204. - ERROR: 'error',
  2205. - RESIZE: 'resize',
  2206. - SCROLL: 'scroll',
  2207. - FULLSCREEN_CHANGE: 'fullscreenchange',
  2208. - WK_FULLSCREEN_CHANGE: 'webkitfullscreenchange',
  2209. + LOAD: "load",
  2210. + BEFORE_UNLOAD: "beforeunload",
  2211. + UNLOAD: "unload",
  2212. + PAGE_SHOW: "pageshow",
  2213. + PAGE_HIDE: "pagehide",
  2214. + PASTE: "paste",
  2215. + ABORT: "abort",
  2216. + ERROR: "error",
  2217. + RESIZE: "resize",
  2218. + SCROLL: "scroll",
  2219. + FULLSCREEN_CHANGE: "fullscreenchange",
  2220. + WK_FULLSCREEN_CHANGE: "webkitfullscreenchange",
  2221. // Form
  2222. - SELECT: 'select',
  2223. - CHANGE: 'change',
  2224. - SUBMIT: 'submit',
  2225. - RESET: 'reset',
  2226. - FOCUS: 'focus',
  2227. - FOCUS_IN: 'focusin',
  2228. - FOCUS_OUT: 'focusout',
  2229. - BLUR: 'blur',
  2230. - INPUT: 'input',
  2231. + SELECT: "select",
  2232. + CHANGE: "change",
  2233. + SUBMIT: "submit",
  2234. + RESET: "reset",
  2235. + FOCUS: "focus",
  2236. + FOCUS_IN: "focusin",
  2237. + FOCUS_OUT: "focusout",
  2238. + BLUR: "blur",
  2239. + INPUT: "input",
  2240. // Local Storage
  2241. - STORAGE: 'storage',
  2242. + STORAGE: "storage",
  2243. // Drag
  2244. - DRAG_START: 'dragstart',
  2245. - DRAG: 'drag',
  2246. - DRAG_ENTER: 'dragenter',
  2247. - DRAG_LEAVE: 'dragleave',
  2248. - DRAG_OVER: 'dragover',
  2249. - DROP: 'drop',
  2250. - DRAG_END: 'dragend',
  2251. + DRAG_START: "dragstart",
  2252. + DRAG: "drag",
  2253. + DRAG_ENTER: "dragenter",
  2254. + DRAG_LEAVE: "dragleave",
  2255. + DRAG_OVER: "dragover",
  2256. + DROP: "drop",
  2257. + DRAG_END: "dragend",
  2258. // Animation
  2259. - ANIMATION_START: browser.isWebKit ? 'webkitAnimationStart' : 'animationstart',
  2260. - ANIMATION_END: browser.isWebKit ? 'webkitAnimationEnd' : 'animationend',
  2261. - ANIMATION_ITERATION: browser.isWebKit ? 'webkitAnimationIteration' : 'animationiteration'
  2262. -} as const;
  2263. + ANIMATION_START: browser.isWebKit ? "webkitAnimationStart" : "animationstart",
  2264. + ANIMATION_END: browser.isWebKit ? "webkitAnimationEnd" : "animationend",
  2265. + ANIMATION_ITERATION: browser.isWebKit ? "webkitAnimationIteration" : "animationiteration",
  2266. +} as const
  2267. export interface EventLike {
  2268. - preventDefault(): void;
  2269. - stopPropagation(): void;
  2270. + preventDefault(): void
  2271. + stopPropagation(): void
  2272. }
  2273. export function isEventLike(obj: unknown): obj is EventLike {
  2274. - const candidate = obj as EventLike | undefined;
  2275. + const candidate = obj as EventLike | undefined
  2276. - return !!(candidate && typeof candidate.preventDefault === 'function' && typeof candidate.stopPropagation === 'function');
  2277. + return !!(
  2278. + candidate &&
  2279. + typeof candidate.preventDefault === "function" &&
  2280. + typeof candidate.stopPropagation === "function"
  2281. + )
  2282. }
  2283. export const EventHelper = {
  2284. stop: <T extends EventLike>(e: T, cancelBubble?: boolean): T => {
  2285. - e.preventDefault();
  2286. + e.preventDefault()
  2287. if (cancelBubble) {
  2288. - e.stopPropagation();
  2289. + e.stopPropagation()
  2290. }
  2291. - return e;
  2292. - }
  2293. -};
  2294. + return e
  2295. + },
  2296. +}
  2297. export interface IFocusTracker extends Disposable {
  2298. - readonly onDidFocus: event.Event<void>;
  2299. - readonly onDidBlur: event.Event<void>;
  2300. - refreshState(): void;
  2301. + readonly onDidFocus: event.Event<void>
  2302. + readonly onDidBlur: event.Event<void>
  2303. + refreshState(): void
  2304. }
  2305. export function saveParentsScrollTop(node: Element): number[] {
  2306. - const r: number[] = [];
  2307. + const r: number[] = []
  2308. for (let i = 0; node && node.nodeType === node.ELEMENT_NODE; i++) {
  2309. - r[i] = node.scrollTop;
  2310. - node = <Element>node.parentNode;
  2311. + r[i] = node.scrollTop
  2312. + node = <Element>node.parentNode
  2313. }
  2314. - return r;
  2315. + return r
  2316. }
  2317. export function restoreParentsScrollTop(node: Element, state: number[]): void {
  2318. for (let i = 0; node && node.nodeType === node.ELEMENT_NODE; i++) {
  2319. if (node.scrollTop !== state[i]) {
  2320. - node.scrollTop = state[i];
  2321. + node.scrollTop = state[i]
  2322. }
  2323. - node = <Element>node.parentNode;
  2324. + node = <Element>node.parentNode
  2325. }
  2326. }
  2327. class FocusTracker extends Disposable implements IFocusTracker {
  2328. + private readonly _onDidFocus = this._register(new event.Emitter<void>())
  2329. + readonly onDidFocus = this._onDidFocus.event
  2330. - private readonly _onDidFocus = this._register(new event.Emitter<void>());
  2331. - readonly onDidFocus = this._onDidFocus.event;
  2332. + private readonly _onDidBlur = this._register(new event.Emitter<void>())
  2333. + readonly onDidBlur = this._onDidBlur.event
  2334. - private readonly _onDidBlur = this._register(new event.Emitter<void>());
  2335. - readonly onDidBlur = this._onDidBlur.event;
  2336. -
  2337. - private _refreshStateHandler: () => void;
  2338. + private _refreshStateHandler: () => void
  2339. private static hasFocusWithin(element: HTMLElement | Window): boolean {
  2340. if (isHTMLElement(element)) {
  2341. - const shadowRoot = getShadowRoot(element);
  2342. - const activeElement = (shadowRoot ? shadowRoot.activeElement : element.ownerDocument.activeElement);
  2343. - return isAncestor(activeElement, element);
  2344. + const shadowRoot = getShadowRoot(element)
  2345. + const activeElement = shadowRoot ? shadowRoot.activeElement : element.ownerDocument.activeElement
  2346. + return isAncestor(activeElement, element)
  2347. } else {
  2348. - const window = element;
  2349. - return isAncestor(window.document.activeElement, window.document);
  2350. + const window = element
  2351. + return isAncestor(window.document.activeElement, window.document)
  2352. }
  2353. }
  2354. constructor(element: HTMLElement | Window) {
  2355. - super();
  2356. - let hasFocus = FocusTracker.hasFocusWithin(element);
  2357. - let loosingFocus = false;
  2358. + super()
  2359. + let hasFocus = FocusTracker.hasFocusWithin(element)
  2360. + let loosingFocus = false
  2361. const onFocus = () => {
  2362. - loosingFocus = false;
  2363. + loosingFocus = false
  2364. if (!hasFocus) {
  2365. - hasFocus = true;
  2366. - this._onDidFocus.fire();
  2367. + hasFocus = true
  2368. + this._onDidFocus.fire()
  2369. }
  2370. - };
  2371. + }
  2372. const onBlur = () => {
  2373. if (hasFocus) {
  2374. - loosingFocus = true;
  2375. - (isHTMLElement(element) ? getWindow(element) : element).setTimeout(() => {
  2376. + loosingFocus = true
  2377. + ;(isHTMLElement(element) ? getWindow(element) : element).setTimeout(() => {
  2378. if (loosingFocus) {
  2379. - loosingFocus = false;
  2380. - hasFocus = false;
  2381. - this._onDidBlur.fire();
  2382. + loosingFocus = false
  2383. + hasFocus = false
  2384. + this._onDidBlur.fire()
  2385. }
  2386. - }, 0);
  2387. + }, 0)
  2388. }
  2389. - };
  2390. + }
  2391. this._refreshStateHandler = () => {
  2392. - const currentNodeHasFocus = FocusTracker.hasFocusWithin(<HTMLElement>element);
  2393. + const currentNodeHasFocus = FocusTracker.hasFocusWithin(<HTMLElement>element)
  2394. if (currentNodeHasFocus !== hasFocus) {
  2395. if (hasFocus) {
  2396. - onBlur();
  2397. + onBlur()
  2398. } else {
  2399. - onFocus();
  2400. + onFocus()
  2401. }
  2402. }
  2403. - };
  2404. + }
  2405. - this._register(addDisposableListener(element, EventType.FOCUS, onFocus, true));
  2406. - this._register(addDisposableListener(element, EventType.BLUR, onBlur, true));
  2407. + this._register(addDisposableListener(element, EventType.FOCUS, onFocus, true))
  2408. + this._register(addDisposableListener(element, EventType.BLUR, onBlur, true))
  2409. if (isHTMLElement(element)) {
  2410. - this._register(addDisposableListener(element, EventType.FOCUS_IN, () => this._refreshStateHandler()));
  2411. - this._register(addDisposableListener(element, EventType.FOCUS_OUT, () => this._refreshStateHandler()));
  2412. + this._register(addDisposableListener(element, EventType.FOCUS_IN, () => this._refreshStateHandler()))
  2413. + this._register(addDisposableListener(element, EventType.FOCUS_OUT, () => this._refreshStateHandler()))
  2414. }
  2415. -
  2416. }
  2417. refreshState() {
  2418. - this._refreshStateHandler();
  2419. + this._refreshStateHandler()
  2420. }
  2421. }
  2422. @@ -1255,153 +1373,165 @@ class FocusTracker extends Disposable implements IFocusTracker {
  2423. * @returns An `IFocusTracker` instance.
  2424. */
  2425. export function trackFocus(element: HTMLElement | Window): IFocusTracker {
  2426. - return new FocusTracker(element);
  2427. + return new FocusTracker(element)
  2428. }
  2429. export function after<T extends Node>(sibling: HTMLElement, child: T): T {
  2430. - sibling.after(child);
  2431. - return child;
  2432. + sibling.after(child)
  2433. + return child
  2434. }
  2435. -export function append<T extends Node>(parent: HTMLElement, child: T): T;
  2436. -export function append<T extends Node>(parent: HTMLElement, ...children: (T | string)[]): void;
  2437. +export function append<T extends Node>(parent: HTMLElement, child: T): T
  2438. +export function append<T extends Node>(parent: HTMLElement, ...children: (T | string)[]): void
  2439. export function append<T extends Node>(parent: HTMLElement, ...children: (T | string)[]): T | void {
  2440. - parent.append(...children);
  2441. - if (children.length === 1 && typeof children[0] !== 'string') {
  2442. - return <T>children[0];
  2443. + parent.append(...children)
  2444. + if (children.length === 1 && typeof children[0] !== "string") {
  2445. + return <T>children[0]
  2446. }
  2447. }
  2448. export function prepend<T extends Node>(parent: HTMLElement, child: T): T {
  2449. - parent.insertBefore(child, parent.firstChild);
  2450. - return child;
  2451. + parent.insertBefore(child, parent.firstChild)
  2452. + return child
  2453. }
  2454. /**
  2455. * Removes all children from `parent` and appends `children`
  2456. */
  2457. export function reset(parent: HTMLElement, ...children: Array<Node | string>): void {
  2458. - parent.innerText = '';
  2459. - append(parent, ...children);
  2460. + parent.innerText = ""
  2461. + append(parent, ...children)
  2462. }
  2463. -const SELECTOR_REGEX = /([\w\-]+)?(#([\w\-]+))?((\.([\w\-]+))*)/;
  2464. +const SELECTOR_REGEX = /([\w\-]+)?(#([\w\-]+))?((\.([\w\-]+))*)/
  2465. export enum Namespace {
  2466. - HTML = 'http://www.w3.org/1999/xhtml',
  2467. - SVG = 'http://www.w3.org/2000/svg'
  2468. + HTML = "http://www.w3.org/1999/xhtml",
  2469. + SVG = "http://www.w3.org/2000/svg",
  2470. }
  2471. -function _$<T extends Element>(namespace: Namespace, description: string, attrs?: { [key: string]: any }, ...children: Array<Node | string>): T {
  2472. - const match = SELECTOR_REGEX.exec(description);
  2473. +function _$<T extends Element>(
  2474. + namespace: Namespace,
  2475. + description: string,
  2476. + attrs?: { [key: string]: any },
  2477. + ...children: Array<Node | string>
  2478. +): T {
  2479. + const match = SELECTOR_REGEX.exec(description)
  2480. if (!match) {
  2481. - throw new Error('Bad use of emmet');
  2482. + throw new Error("Bad use of emmet")
  2483. }
  2484. - const tagName = match[1] || 'div';
  2485. - let result: T;
  2486. + const tagName = match[1] || "div"
  2487. + let result: T
  2488. if (namespace !== Namespace.HTML) {
  2489. - result = document.createElementNS(namespace as string, tagName) as T;
  2490. + result = document.createElementNS(namespace as string, tagName) as T
  2491. } else {
  2492. - result = document.createElement(tagName) as unknown as T;
  2493. + result = document.createElement(tagName) as unknown as T
  2494. }
  2495. if (match[3]) {
  2496. - result.id = match[3];
  2497. + result.id = match[3]
  2498. }
  2499. if (match[4]) {
  2500. - result.className = match[4].replace(/\./g, ' ').trim();
  2501. + result.className = match[4].replace(/\./g, " ").trim()
  2502. }
  2503. if (attrs) {
  2504. Object.entries(attrs).forEach(([name, value]) => {
  2505. - if (typeof value === 'undefined') {
  2506. - return;
  2507. + if (typeof value === "undefined") {
  2508. + return
  2509. }
  2510. if (/^on\w+$/.test(name)) {
  2511. - (<any>result)[name] = value;
  2512. - } else if (name === 'selected') {
  2513. + ;(<any>result)[name] = value
  2514. + } else if (name === "selected") {
  2515. if (value) {
  2516. - result.setAttribute(name, 'true');
  2517. + result.setAttribute(name, "true")
  2518. }
  2519. -
  2520. } else {
  2521. - result.setAttribute(name, value);
  2522. + result.setAttribute(name, value)
  2523. }
  2524. - });
  2525. + })
  2526. }
  2527. - result.append(...children);
  2528. + result.append(...children)
  2529. - return result as T;
  2530. + return result as T
  2531. }
  2532. -export function $<T extends HTMLElement>(description: string, attrs?: { [key: string]: any }, ...children: Array<Node | string>): T {
  2533. - return _$(Namespace.HTML, description, attrs, ...children);
  2534. +export function $<T extends HTMLElement>(
  2535. + description: string,
  2536. + attrs?: { [key: string]: any },
  2537. + ...children: Array<Node | string>
  2538. +): T {
  2539. + return _$(Namespace.HTML, description, attrs, ...children)
  2540. }
  2541. -$.SVG = function <T extends SVGElement>(description: string, attrs?: { [key: string]: any }, ...children: Array<Node | string>): T {
  2542. - return _$(Namespace.SVG, description, attrs, ...children);
  2543. -};
  2544. +$.SVG = function <T extends SVGElement>(
  2545. + description: string,
  2546. + attrs?: { [key: string]: any },
  2547. + ...children: Array<Node | string>
  2548. +): T {
  2549. + return _$(Namespace.SVG, description, attrs, ...children)
  2550. +}
  2551. export function join(nodes: Node[], separator: Node | string): Node[] {
  2552. - const result: Node[] = [];
  2553. + const result: Node[] = []
  2554. nodes.forEach((node, index) => {
  2555. if (index > 0) {
  2556. if (separator instanceof Node) {
  2557. - result.push(separator.cloneNode());
  2558. + result.push(separator.cloneNode())
  2559. } else {
  2560. - result.push(document.createTextNode(separator));
  2561. + result.push(document.createTextNode(separator))
  2562. }
  2563. }
  2564. - result.push(node);
  2565. - });
  2566. + result.push(node)
  2567. + })
  2568. - return result;
  2569. + return result
  2570. }
  2571. export function setVisibility(visible: boolean, ...elements: HTMLElement[]): void {
  2572. if (visible) {
  2573. - show(...elements);
  2574. + show(...elements)
  2575. } else {
  2576. - hide(...elements);
  2577. + hide(...elements)
  2578. }
  2579. }
  2580. export function show(...elements: HTMLElement[]): void {
  2581. for (const element of elements) {
  2582. - element.style.display = '';
  2583. - element.removeAttribute('aria-hidden');
  2584. + element.style.display = ""
  2585. + element.removeAttribute("aria-hidden")
  2586. }
  2587. }
  2588. export function hide(...elements: HTMLElement[]): void {
  2589. for (const element of elements) {
  2590. - element.style.display = 'none';
  2591. - element.setAttribute('aria-hidden', 'true');
  2592. + element.style.display = "none"
  2593. + element.setAttribute("aria-hidden", "true")
  2594. }
  2595. }
  2596. function findParentWithAttribute(node: Node | null, attribute: string): HTMLElement | null {
  2597. while (node && node.nodeType === node.ELEMENT_NODE) {
  2598. if (isHTMLElement(node) && node.hasAttribute(attribute)) {
  2599. - return node;
  2600. + return node
  2601. }
  2602. - node = node.parentNode;
  2603. + node = node.parentNode
  2604. }
  2605. - return null;
  2606. + return null
  2607. }
  2608. export function removeTabIndexAndUpdateFocus(node: HTMLElement): void {
  2609. - if (!node || !node.hasAttribute('tabIndex')) {
  2610. - return;
  2611. + if (!node || !node.hasAttribute("tabIndex")) {
  2612. + return
  2613. }
  2614. // If we are the currently focused element and tabIndex is removed,
  2615. @@ -1409,35 +1539,35 @@ export function removeTabIndexAndUpdateFocus(node: HTMLElement): void {
  2616. // typically never want that, rather put focus to the closest element
  2617. // in the hierarchy of the parent DOM nodes.
  2618. if (node.ownerDocument.activeElement === node) {
  2619. - const parentFocusable = findParentWithAttribute(node.parentElement, 'tabIndex');
  2620. - parentFocusable?.focus();
  2621. + const parentFocusable = findParentWithAttribute(node.parentElement, "tabIndex")
  2622. + parentFocusable?.focus()
  2623. }
  2624. - node.removeAttribute('tabindex');
  2625. + node.removeAttribute("tabindex")
  2626. }
  2627. export function finalHandler<T extends Event>(fn: (event: T) => unknown): (event: T) => unknown {
  2628. - return e => {
  2629. - e.preventDefault();
  2630. - e.stopPropagation();
  2631. - fn(e);
  2632. - };
  2633. + return (e) => {
  2634. + e.preventDefault()
  2635. + e.stopPropagation()
  2636. + fn(e)
  2637. + }
  2638. }
  2639. export function domContentLoaded(targetWindow: Window): Promise<void> {
  2640. - return new Promise<void>(resolve => {
  2641. - const readyState = targetWindow.document.readyState;
  2642. - if (readyState === 'complete' || (targetWindow.document && targetWindow.document.body !== null)) {
  2643. - resolve(undefined);
  2644. + return new Promise<void>((resolve) => {
  2645. + const readyState = targetWindow.document.readyState
  2646. + if (readyState === "complete" || (targetWindow.document && targetWindow.document.body !== null)) {
  2647. + resolve(undefined)
  2648. } else {
  2649. const listener = () => {
  2650. - targetWindow.window.removeEventListener('DOMContentLoaded', listener, false);
  2651. - resolve();
  2652. - };
  2653. + targetWindow.window.removeEventListener("DOMContentLoaded", listener, false)
  2654. + resolve()
  2655. + }
  2656. - targetWindow.window.addEventListener('DOMContentLoaded', listener, false);
  2657. + targetWindow.window.addEventListener("DOMContentLoaded", listener, false)
  2658. }
  2659. - });
  2660. + })
  2661. }
  2662. /**
  2663. @@ -1449,8 +1579,8 @@ export function domContentLoaded(targetWindow: Window): Promise<void> {
  2664. * with the screen pixels, it will sometimes be rendered with 2 screen pixels, and sometimes with 3 screen pixels.
  2665. */
  2666. export function computeScreenAwareSize(window: Window, cssPx: number): number {
  2667. - const screenPx = window.devicePixelRatio * cssPx;
  2668. - return Math.max(1, Math.floor(screenPx)) / window.devicePixelRatio;
  2669. + const screenPx = window.devicePixelRatio * cssPx
  2670. + return Math.max(1, Math.floor(screenPx)) / window.devicePixelRatio
  2671. }
  2672. /**
  2673. @@ -1471,7 +1601,7 @@ export function windowOpenNoOpener(url: string): void {
  2674. // See https://developer.mozilla.org/en-US/docs/Web/API/Window/open#noopener
  2675. // However, this also doesn't allow us to realize if the browser blocked
  2676. // the creation of the window.
  2677. - mainWindow.open(url, '_blank', 'noopener');
  2678. + mainWindow.open(url, "_blank", "noopener")
  2679. }
  2680. /**
  2681. @@ -1485,15 +1615,12 @@ export function windowOpenNoOpener(url: string): void {
  2682. *
  2683. * In otherwords, you should almost always use {@link windowOpenNoOpener} instead of this function.
  2684. */
  2685. -const popupWidth = 780, popupHeight = 640;
  2686. +const popupWidth = 780,
  2687. + popupHeight = 640
  2688. export function windowOpenPopup(url: string): void {
  2689. - const left = Math.floor(mainWindow.screenLeft + mainWindow.innerWidth / 2 - popupWidth / 2);
  2690. - const top = Math.floor(mainWindow.screenTop + mainWindow.innerHeight / 2 - popupHeight / 2);
  2691. - mainWindow.open(
  2692. - url,
  2693. - '_blank',
  2694. - `width=${popupWidth},height=${popupHeight},top=${top},left=${left}`
  2695. - );
  2696. + const left = Math.floor(mainWindow.screenLeft + mainWindow.innerWidth / 2 - popupWidth / 2)
  2697. + const top = Math.floor(mainWindow.screenTop + mainWindow.innerHeight / 2 - popupHeight / 2)
  2698. + mainWindow.open(url, "_blank", `width=${popupWidth},height=${popupHeight},top=${top},left=${left}`)
  2699. }
  2700. /**
  2701. @@ -1512,86 +1639,83 @@ export function windowOpenPopup(url: string): void {
  2702. * @returns boolean indicating if the {@link window.open} call succeeded
  2703. */
  2704. export function windowOpenWithSuccess(url: string, noOpener = true): boolean {
  2705. - const newTab = mainWindow.open();
  2706. + const newTab = mainWindow.open()
  2707. if (newTab) {
  2708. if (noOpener) {
  2709. // see `windowOpenNoOpener` for details on why this is important
  2710. - (newTab as any).opener = null;
  2711. + ;(newTab as any).opener = null
  2712. }
  2713. - newTab.location.href = url;
  2714. - return true;
  2715. + newTab.location.href = url
  2716. + return true
  2717. }
  2718. - return false;
  2719. + return false
  2720. }
  2721. export function animate(targetWindow: Window, fn: () => void): IDisposable {
  2722. const step = () => {
  2723. - fn();
  2724. - stepDisposable = scheduleAtNextAnimationFrame(targetWindow, step);
  2725. - };
  2726. + fn()
  2727. + stepDisposable = scheduleAtNextAnimationFrame(targetWindow, step)
  2728. + }
  2729. - let stepDisposable = scheduleAtNextAnimationFrame(targetWindow, step);
  2730. - return toDisposable(() => stepDisposable.dispose());
  2731. + let stepDisposable = scheduleAtNextAnimationFrame(targetWindow, step)
  2732. + return toDisposable(() => stepDisposable.dispose())
  2733. }
  2734. -RemoteAuthorities.setPreferredWebSchema(/^https:/.test(mainWindow.location.href) ? 'https' : 'http');
  2735. +RemoteAuthorities.setPreferredWebSchema(/^https:/.test(mainWindow.location.href) ? "https" : "http")
  2736. export function triggerDownload(dataOrUri: Uint8Array | URI, name: string): void {
  2737. -
  2738. // If the data is provided as Buffer, we create a
  2739. // blob URL out of it to produce a valid link
  2740. - let url: string;
  2741. + let url: string
  2742. if (URI.isUri(dataOrUri)) {
  2743. - url = dataOrUri.toString(true);
  2744. + url = dataOrUri.toString(true)
  2745. } else {
  2746. - const blob = new Blob([dataOrUri]);
  2747. - url = URL.createObjectURL(blob);
  2748. + const blob = new Blob([dataOrUri as Uint8Array<ArrayBuffer>])
  2749. + url = URL.createObjectURL(blob)
  2750. // Ensure to free the data from DOM eventually
  2751. - setTimeout(() => URL.revokeObjectURL(url));
  2752. + setTimeout(() => URL.revokeObjectURL(url))
  2753. }
  2754. // In order to download from the browser, the only way seems
  2755. // to be creating a <a> element with download attribute that
  2756. // points to the file to download.
  2757. // See also https://developers.google.com/web/updates/2011/08/Downloading-resources-in-HTML5-a-download
  2758. - const activeWindow = getActiveWindow();
  2759. - const anchor = document.createElement('a');
  2760. - activeWindow.document.body.appendChild(anchor);
  2761. - anchor.download = name;
  2762. - anchor.href = url;
  2763. - anchor.click();
  2764. + const activeWindow = getActiveWindow()
  2765. + const anchor = document.createElement("a")
  2766. + activeWindow.document.body.appendChild(anchor)
  2767. + anchor.download = name
  2768. + anchor.href = url
  2769. + anchor.click()
  2770. // Ensure to remove the element from DOM eventually
  2771. - setTimeout(() => anchor.remove());
  2772. + setTimeout(() => anchor.remove())
  2773. }
  2774. export function triggerUpload(): Promise<FileList | undefined> {
  2775. - return new Promise<FileList | undefined>(resolve => {
  2776. -
  2777. + return new Promise<FileList | undefined>((resolve) => {
  2778. // In order to upload to the browser, create a
  2779. // input element of type `file` and click it
  2780. // to gather the selected files
  2781. - const activeWindow = getActiveWindow();
  2782. - const input = document.createElement('input');
  2783. - activeWindow.document.body.appendChild(input);
  2784. - input.type = 'file';
  2785. - input.multiple = true;
  2786. + const activeWindow = getActiveWindow()
  2787. + const input = document.createElement("input")
  2788. + activeWindow.document.body.appendChild(input)
  2789. + input.type = "file"
  2790. + input.multiple = true
  2791. // Resolve once the input event has fired once
  2792. - event.Event.once(event.Event.fromDOMEventEmitter(input, 'input'))(() => {
  2793. - resolve(input.files ?? undefined);
  2794. - });
  2795. + event.Event.once(event.Event.fromDOMEventEmitter(input, "input"))(() => {
  2796. + resolve(input.files ?? undefined)
  2797. + })
  2798. - input.click();
  2799. + input.click()
  2800. // Ensure to remove the element from DOM eventually
  2801. - setTimeout(() => input.remove());
  2802. - });
  2803. + setTimeout(() => input.remove())
  2804. + })
  2805. }
  2806. export enum DetectedFullscreenMode {
  2807. -
  2808. /**
  2809. * The document is fullscreen, e.g. because an element
  2810. * in the document requested to be fullscreen.
  2811. @@ -1602,28 +1726,30 @@ export enum DetectedFullscreenMode {
  2812. * The browser is fullscreen, e.g. because the user enabled
  2813. * native window fullscreen for it.
  2814. */
  2815. - BROWSER
  2816. + BROWSER,
  2817. }
  2818. export interface IDetectedFullscreen {
  2819. -
  2820. /**
  2821. * Figure out if the document is fullscreen or the browser.
  2822. */
  2823. - mode: DetectedFullscreenMode;
  2824. + mode: DetectedFullscreenMode
  2825. /**
  2826. * Whether we know for sure that we are in fullscreen mode or
  2827. * it is a guess.
  2828. */
  2829. - guess: boolean;
  2830. + guess: boolean
  2831. }
  2832. export function detectFullscreen(targetWindow: Window): IDetectedFullscreen | null {
  2833. -
  2834. // Browser fullscreen: use DOM APIs to detect
  2835. - if (targetWindow.document.fullscreenElement || (<any>targetWindow.document).webkitFullscreenElement || (<any>targetWindow.document).webkitIsFullScreen) {
  2836. - return { mode: DetectedFullscreenMode.DOCUMENT, guess: false };
  2837. + if (
  2838. + targetWindow.document.fullscreenElement ||
  2839. + (<any>targetWindow.document).webkitFullscreenElement ||
  2840. + (<any>targetWindow.document).webkitIsFullScreen
  2841. + ) {
  2842. + return { mode: DetectedFullscreenMode.DOCUMENT, guess: false }
  2843. }
  2844. // There is no standard way to figure out if the browser
  2845. @@ -1635,22 +1761,25 @@ export function detectFullscreen(targetWindow: Window): IDetectedFullscreen | nu
  2846. // if the height of the window matches the screen height, we can
  2847. // safely assume that the browser is fullscreen because no browser
  2848. // chrome is taking height away (e.g. like toolbars).
  2849. - return { mode: DetectedFullscreenMode.BROWSER, guess: false };
  2850. + return { mode: DetectedFullscreenMode.BROWSER, guess: false }
  2851. }
  2852. if (platform.isMacintosh || platform.isLinux) {
  2853. // macOS and Linux do not properly report `innerHeight`, only Windows does
  2854. - if (targetWindow.outerHeight === targetWindow.screen.height && targetWindow.outerWidth === targetWindow.screen.width) {
  2855. + if (
  2856. + targetWindow.outerHeight === targetWindow.screen.height &&
  2857. + targetWindow.outerWidth === targetWindow.screen.width
  2858. + ) {
  2859. // if the height of the browser matches the screen height, we can
  2860. // only guess that we are in fullscreen. It is also possible that
  2861. // the user has turned off taskbars in the OS and the browser is
  2862. // simply able to span the entire size of the screen.
  2863. - return { mode: DetectedFullscreenMode.BROWSER, guess: true };
  2864. + return { mode: DetectedFullscreenMode.BROWSER, guess: true }
  2865. }
  2866. }
  2867. // Not in fullscreen
  2868. - return null;
  2869. + return null
  2870. }
  2871. // -- sanitize and trusted html
  2872. @@ -1659,136 +1788,184 @@ export function detectFullscreen(targetWindow: Window): IDetectedFullscreen | nu
  2873. * Hooks dompurify using `afterSanitizeAttributes` to check that all `href` and `src`
  2874. * attributes are valid.
  2875. */
  2876. -export function hookDomPurifyHrefAndSrcSanitizer(allowedProtocols: readonly string[], allowDataImages = false): IDisposable {
  2877. +export function hookDomPurifyHrefAndSrcSanitizer(
  2878. + allowedProtocols: readonly string[],
  2879. + allowDataImages = false,
  2880. +): IDisposable {
  2881. // https://github.com/cure53/DOMPurify/blob/main/demos/hooks-scheme-allowlist.html
  2882. // build an anchor to map URLs to
  2883. - const anchor = document.createElement('a');
  2884. + const anchor = document.createElement("a")
  2885. - dompurify.addHook('afterSanitizeAttributes', (node) => {
  2886. + dompurify.addHook("afterSanitizeAttributes", (node) => {
  2887. // check all href/src attributes for validity
  2888. - for (const attr of ['href', 'src']) {
  2889. + for (const attr of ["href", "src"]) {
  2890. if (node.hasAttribute(attr)) {
  2891. - const attrValue = node.getAttribute(attr) as string;
  2892. - if (attr === 'href' && attrValue.startsWith('#')) {
  2893. + const attrValue = node.getAttribute(attr) as string
  2894. + if (attr === "href" && attrValue.startsWith("#")) {
  2895. // Allow fragment links
  2896. - continue;
  2897. + continue
  2898. }
  2899. - anchor.href = attrValue;
  2900. - if (!allowedProtocols.includes(anchor.protocol.replace(/:$/, ''))) {
  2901. - if (allowDataImages && attr === 'src' && anchor.href.startsWith('data:')) {
  2902. - continue;
  2903. + anchor.href = attrValue
  2904. + if (!allowedProtocols.includes(anchor.protocol.replace(/:$/, ""))) {
  2905. + if (allowDataImages && attr === "src" && anchor.href.startsWith("data:")) {
  2906. + continue
  2907. }
  2908. - node.removeAttribute(attr);
  2909. + node.removeAttribute(attr)
  2910. }
  2911. }
  2912. }
  2913. - });
  2914. + })
  2915. return toDisposable(() => {
  2916. - dompurify.removeHook('afterSanitizeAttributes');
  2917. - });
  2918. + dompurify.removeHook("afterSanitizeAttributes")
  2919. + })
  2920. }
  2921. -const defaultSafeProtocols = [
  2922. - Schemas.http,
  2923. - Schemas.https,
  2924. - Schemas.command,
  2925. -];
  2926. +const defaultSafeProtocols = [Schemas.http, Schemas.https, Schemas.command]
  2927. /**
  2928. * List of safe, non-input html tags.
  2929. */
  2930. export const basicMarkupHtmlTags = Object.freeze([
  2931. - 'a',
  2932. - 'abbr',
  2933. - 'b',
  2934. - 'bdo',
  2935. - 'blockquote',
  2936. - 'br',
  2937. - 'caption',
  2938. - 'cite',
  2939. - 'code',
  2940. - 'col',
  2941. - 'colgroup',
  2942. - 'dd',
  2943. - 'del',
  2944. - 'details',
  2945. - 'dfn',
  2946. - 'div',
  2947. - 'dl',
  2948. - 'dt',
  2949. - 'em',
  2950. - 'figcaption',
  2951. - 'figure',
  2952. - 'h1',
  2953. - 'h2',
  2954. - 'h3',
  2955. - 'h4',
  2956. - 'h5',
  2957. - 'h6',
  2958. - 'hr',
  2959. - 'i',
  2960. - 'img',
  2961. - 'input',
  2962. - 'ins',
  2963. - 'kbd',
  2964. - 'label',
  2965. - 'li',
  2966. - 'mark',
  2967. - 'ol',
  2968. - 'p',
  2969. - 'pre',
  2970. - 'q',
  2971. - 'rp',
  2972. - 'rt',
  2973. - 'ruby',
  2974. - 'samp',
  2975. - 'small',
  2976. - 'small',
  2977. - 'source',
  2978. - 'span',
  2979. - 'strike',
  2980. - 'strong',
  2981. - 'sub',
  2982. - 'summary',
  2983. - 'sup',
  2984. - 'table',
  2985. - 'tbody',
  2986. - 'td',
  2987. - 'tfoot',
  2988. - 'th',
  2989. - 'thead',
  2990. - 'time',
  2991. - 'tr',
  2992. - 'tt',
  2993. - 'u',
  2994. - 'ul',
  2995. - 'var',
  2996. - 'video',
  2997. - 'wbr',
  2998. -]);
  2999. + "a",
  3000. + "abbr",
  3001. + "b",
  3002. + "bdo",
  3003. + "blockquote",
  3004. + "br",
  3005. + "caption",
  3006. + "cite",
  3007. + "code",
  3008. + "col",
  3009. + "colgroup",
  3010. + "dd",
  3011. + "del",
  3012. + "details",
  3013. + "dfn",
  3014. + "div",
  3015. + "dl",
  3016. + "dt",
  3017. + "em",
  3018. + "figcaption",
  3019. + "figure",
  3020. + "h1",
  3021. + "h2",
  3022. + "h3",
  3023. + "h4",
  3024. + "h5",
  3025. + "h6",
  3026. + "hr",
  3027. + "i",
  3028. + "img",
  3029. + "input",
  3030. + "ins",
  3031. + "kbd",
  3032. + "label",
  3033. + "li",
  3034. + "mark",
  3035. + "ol",
  3036. + "p",
  3037. + "pre",
  3038. + "q",
  3039. + "rp",
  3040. + "rt",
  3041. + "ruby",
  3042. + "samp",
  3043. + "small",
  3044. + "small",
  3045. + "source",
  3046. + "span",
  3047. + "strike",
  3048. + "strong",
  3049. + "sub",
  3050. + "summary",
  3051. + "sup",
  3052. + "table",
  3053. + "tbody",
  3054. + "td",
  3055. + "tfoot",
  3056. + "th",
  3057. + "thead",
  3058. + "time",
  3059. + "tr",
  3060. + "tt",
  3061. + "u",
  3062. + "ul",
  3063. + "var",
  3064. + "video",
  3065. + "wbr",
  3066. +])
  3067. const defaultDomPurifyConfig = Object.freeze<dompurify.Config & { RETURN_TRUSTED_TYPE: true }>({
  3068. - ALLOWED_TAGS: ['a', 'button', 'blockquote', 'code', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'input', 'label', 'li', 'p', 'pre', 'select', 'small', 'span', 'strong', 'textarea', 'ul', 'ol'],
  3069. - ALLOWED_ATTR: ['href', 'data-href', 'data-command', 'target', 'title', 'name', 'src', 'alt', 'class', 'id', 'role', 'tabindex', 'style', 'data-code', 'width', 'height', 'align', 'x-dispatch', 'required', 'checked', 'placeholder', 'type', 'start'],
  3070. + ALLOWED_TAGS: [
  3071. + "a",
  3072. + "button",
  3073. + "blockquote",
  3074. + "code",
  3075. + "div",
  3076. + "h1",
  3077. + "h2",
  3078. + "h3",
  3079. + "h4",
  3080. + "h5",
  3081. + "h6",
  3082. + "hr",
  3083. + "input",
  3084. + "label",
  3085. + "li",
  3086. + "p",
  3087. + "pre",
  3088. + "select",
  3089. + "small",
  3090. + "span",
  3091. + "strong",
  3092. + "textarea",
  3093. + "ul",
  3094. + "ol",
  3095. + ],
  3096. + ALLOWED_ATTR: [
  3097. + "href",
  3098. + "data-href",
  3099. + "data-command",
  3100. + "target",
  3101. + "title",
  3102. + "name",
  3103. + "src",
  3104. + "alt",
  3105. + "class",
  3106. + "id",
  3107. + "role",
  3108. + "tabindex",
  3109. + "style",
  3110. + "data-code",
  3111. + "width",
  3112. + "height",
  3113. + "align",
  3114. + "x-dispatch",
  3115. + "required",
  3116. + "checked",
  3117. + "placeholder",
  3118. + "type",
  3119. + "start",
  3120. + ],
  3121. RETURN_DOM: false,
  3122. RETURN_DOM_FRAGMENT: false,
  3123. - RETURN_TRUSTED_TYPE: true
  3124. -});
  3125. + RETURN_TRUSTED_TYPE: true,
  3126. +})
  3127. /**
  3128. * Sanitizes the given `value` and reset the given `node` with it.
  3129. */
  3130. export function safeInnerHtml(node: HTMLElement, value: string, extraDomPurifyConfig?: dompurify.Config): void {
  3131. - const hook = hookDomPurifyHrefAndSrcSanitizer(defaultSafeProtocols);
  3132. + const hook = hookDomPurifyHrefAndSrcSanitizer(defaultSafeProtocols)
  3133. try {
  3134. - const html = dompurify.sanitize(value, { ...defaultDomPurifyConfig, ...extraDomPurifyConfig });
  3135. - node.innerHTML = html as unknown as string;
  3136. + const html = dompurify.sanitize(value, { ...defaultDomPurifyConfig, ...extraDomPurifyConfig })
  3137. + node.innerHTML = html as unknown as string
  3138. } finally {
  3139. - hook.dispose();
  3140. + hook.dispose()
  3141. }
  3142. }
  3143. @@ -1798,16 +1975,16 @@ export function safeInnerHtml(node: HTMLElement, value: string, extraDomPurifyCo
  3144. * From https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/btoa
  3145. */
  3146. function toBinary(str: string): string {
  3147. - const codeUnits = new Uint16Array(str.length);
  3148. + const codeUnits = new Uint16Array(str.length)
  3149. for (let i = 0; i < codeUnits.length; i++) {
  3150. - codeUnits[i] = str.charCodeAt(i);
  3151. + codeUnits[i] = str.charCodeAt(i)
  3152. }
  3153. - let binary = '';
  3154. - const uint8array = new Uint8Array(codeUnits.buffer);
  3155. + let binary = ""
  3156. + const uint8array = new Uint8Array(codeUnits.buffer)
  3157. for (let i = 0; i < uint8array.length; i++) {
  3158. - binary += String.fromCharCode(uint8array[i]);
  3159. + binary += String.fromCharCode(uint8array[i])
  3160. }
  3161. - return binary;
  3162. + return binary
  3163. }
  3164. /**
  3165. @@ -1815,143 +1992,185 @@ function toBinary(str: string): string {
  3166. * of throwing an exception.
  3167. */
  3168. export function multibyteAwareBtoa(str: string): string {
  3169. - return btoa(toBinary(str));
  3170. + return btoa(toBinary(str))
  3171. }
  3172. -type ModifierKey = 'alt' | 'ctrl' | 'shift' | 'meta';
  3173. +type ModifierKey = "alt" | "ctrl" | "shift" | "meta"
  3174. export interface IModifierKeyStatus {
  3175. - altKey: boolean;
  3176. - shiftKey: boolean;
  3177. - ctrlKey: boolean;
  3178. - metaKey: boolean;
  3179. - lastKeyPressed?: ModifierKey;
  3180. - lastKeyReleased?: ModifierKey;
  3181. - event?: KeyboardEvent;
  3182. + altKey: boolean
  3183. + shiftKey: boolean
  3184. + ctrlKey: boolean
  3185. + metaKey: boolean
  3186. + lastKeyPressed?: ModifierKey
  3187. + lastKeyReleased?: ModifierKey
  3188. + event?: KeyboardEvent
  3189. }
  3190. export class ModifierKeyEmitter extends event.Emitter<IModifierKeyStatus> {
  3191. -
  3192. - private readonly _subscriptions = new DisposableStore();
  3193. - private _keyStatus: IModifierKeyStatus;
  3194. - private static instance: ModifierKeyEmitter;
  3195. + private readonly _subscriptions = new DisposableStore()
  3196. + private _keyStatus: IModifierKeyStatus
  3197. + private static instance: ModifierKeyEmitter
  3198. private constructor() {
  3199. - super();
  3200. + super()
  3201. this._keyStatus = {
  3202. altKey: false,
  3203. shiftKey: false,
  3204. ctrlKey: false,
  3205. - metaKey: false
  3206. - };
  3207. + metaKey: false,
  3208. + }
  3209. - this._subscriptions.add(event.Event.runAndSubscribe(onDidRegisterWindow, ({ window, disposables }) => this.registerListeners(window, disposables), { window: mainWindow, disposables: this._subscriptions }));
  3210. + this._subscriptions.add(
  3211. + event.Event.runAndSubscribe(
  3212. + onDidRegisterWindow,
  3213. + ({ window, disposables }) => this.registerListeners(window, disposables),
  3214. + { window: mainWindow, disposables: this._subscriptions },
  3215. + ),
  3216. + )
  3217. }
  3218. private registerListeners(window: Window, disposables: DisposableStore): void {
  3219. - disposables.add(addDisposableListener(window, 'keydown', e => {
  3220. - if (e.defaultPrevented) {
  3221. - return;
  3222. - }
  3223. -
  3224. - const event = new StandardKeyboardEvent(e);
  3225. - // If Alt-key keydown event is repeated, ignore it #112347
  3226. - // Only known to be necessary for Alt-Key at the moment #115810
  3227. - if (event.keyCode === KeyCode.Alt && e.repeat) {
  3228. - return;
  3229. - }
  3230. -
  3231. - if (e.altKey && !this._keyStatus.altKey) {
  3232. - this._keyStatus.lastKeyPressed = 'alt';
  3233. - } else if (e.ctrlKey && !this._keyStatus.ctrlKey) {
  3234. - this._keyStatus.lastKeyPressed = 'ctrl';
  3235. - } else if (e.metaKey && !this._keyStatus.metaKey) {
  3236. - this._keyStatus.lastKeyPressed = 'meta';
  3237. - } else if (e.shiftKey && !this._keyStatus.shiftKey) {
  3238. - this._keyStatus.lastKeyPressed = 'shift';
  3239. - } else if (event.keyCode !== KeyCode.Alt) {
  3240. - this._keyStatus.lastKeyPressed = undefined;
  3241. - } else {
  3242. - return;
  3243. - }
  3244. -
  3245. - this._keyStatus.altKey = e.altKey;
  3246. - this._keyStatus.ctrlKey = e.ctrlKey;
  3247. - this._keyStatus.metaKey = e.metaKey;
  3248. - this._keyStatus.shiftKey = e.shiftKey;
  3249. + disposables.add(
  3250. + addDisposableListener(
  3251. + window,
  3252. + "keydown",
  3253. + (e) => {
  3254. + if (e.defaultPrevented) {
  3255. + return
  3256. + }
  3257. - if (this._keyStatus.lastKeyPressed) {
  3258. - this._keyStatus.event = e;
  3259. - this.fire(this._keyStatus);
  3260. - }
  3261. - }, true));
  3262. + const event = new StandardKeyboardEvent(e)
  3263. + // If Alt-key keydown event is repeated, ignore it #112347
  3264. + // Only known to be necessary for Alt-Key at the moment #115810
  3265. + if (event.keyCode === KeyCode.Alt && e.repeat) {
  3266. + return
  3267. + }
  3268. - disposables.add(addDisposableListener(window, 'keyup', e => {
  3269. - if (e.defaultPrevented) {
  3270. - return;
  3271. - }
  3272. + if (e.altKey && !this._keyStatus.altKey) {
  3273. + this._keyStatus.lastKeyPressed = "alt"
  3274. + } else if (e.ctrlKey && !this._keyStatus.ctrlKey) {
  3275. + this._keyStatus.lastKeyPressed = "ctrl"
  3276. + } else if (e.metaKey && !this._keyStatus.metaKey) {
  3277. + this._keyStatus.lastKeyPressed = "meta"
  3278. + } else if (e.shiftKey && !this._keyStatus.shiftKey) {
  3279. + this._keyStatus.lastKeyPressed = "shift"
  3280. + } else if (event.keyCode !== KeyCode.Alt) {
  3281. + this._keyStatus.lastKeyPressed = undefined
  3282. + } else {
  3283. + return
  3284. + }
  3285. - if (!e.altKey && this._keyStatus.altKey) {
  3286. - this._keyStatus.lastKeyReleased = 'alt';
  3287. - } else if (!e.ctrlKey && this._keyStatus.ctrlKey) {
  3288. - this._keyStatus.lastKeyReleased = 'ctrl';
  3289. - } else if (!e.metaKey && this._keyStatus.metaKey) {
  3290. - this._keyStatus.lastKeyReleased = 'meta';
  3291. - } else if (!e.shiftKey && this._keyStatus.shiftKey) {
  3292. - this._keyStatus.lastKeyReleased = 'shift';
  3293. - } else {
  3294. - this._keyStatus.lastKeyReleased = undefined;
  3295. - }
  3296. + this._keyStatus.altKey = e.altKey
  3297. + this._keyStatus.ctrlKey = e.ctrlKey
  3298. + this._keyStatus.metaKey = e.metaKey
  3299. + this._keyStatus.shiftKey = e.shiftKey
  3300. - if (this._keyStatus.lastKeyPressed !== this._keyStatus.lastKeyReleased) {
  3301. - this._keyStatus.lastKeyPressed = undefined;
  3302. - }
  3303. + if (this._keyStatus.lastKeyPressed) {
  3304. + this._keyStatus.event = e
  3305. + this.fire(this._keyStatus)
  3306. + }
  3307. + },
  3308. + true,
  3309. + ),
  3310. + )
  3311. - this._keyStatus.altKey = e.altKey;
  3312. - this._keyStatus.ctrlKey = e.ctrlKey;
  3313. - this._keyStatus.metaKey = e.metaKey;
  3314. - this._keyStatus.shiftKey = e.shiftKey;
  3315. + disposables.add(
  3316. + addDisposableListener(
  3317. + window,
  3318. + "keyup",
  3319. + (e) => {
  3320. + if (e.defaultPrevented) {
  3321. + return
  3322. + }
  3323. - if (this._keyStatus.lastKeyReleased) {
  3324. - this._keyStatus.event = e;
  3325. - this.fire(this._keyStatus);
  3326. - }
  3327. - }, true));
  3328. + if (!e.altKey && this._keyStatus.altKey) {
  3329. + this._keyStatus.lastKeyReleased = "alt"
  3330. + } else if (!e.ctrlKey && this._keyStatus.ctrlKey) {
  3331. + this._keyStatus.lastKeyReleased = "ctrl"
  3332. + } else if (!e.metaKey && this._keyStatus.metaKey) {
  3333. + this._keyStatus.lastKeyReleased = "meta"
  3334. + } else if (!e.shiftKey && this._keyStatus.shiftKey) {
  3335. + this._keyStatus.lastKeyReleased = "shift"
  3336. + } else {
  3337. + this._keyStatus.lastKeyReleased = undefined
  3338. + }
  3339. - disposables.add(addDisposableListener(window.document.body, 'mousedown', () => {
  3340. - this._keyStatus.lastKeyPressed = undefined;
  3341. - }, true));
  3342. + if (this._keyStatus.lastKeyPressed !== this._keyStatus.lastKeyReleased) {
  3343. + this._keyStatus.lastKeyPressed = undefined
  3344. + }
  3345. - disposables.add(addDisposableListener(window.document.body, 'mouseup', () => {
  3346. - this._keyStatus.lastKeyPressed = undefined;
  3347. - }, true));
  3348. + this._keyStatus.altKey = e.altKey
  3349. + this._keyStatus.ctrlKey = e.ctrlKey
  3350. + this._keyStatus.metaKey = e.metaKey
  3351. + this._keyStatus.shiftKey = e.shiftKey
  3352. - disposables.add(addDisposableListener(window.document.body, 'mousemove', e => {
  3353. - if (e.buttons) {
  3354. - this._keyStatus.lastKeyPressed = undefined;
  3355. - }
  3356. - }, true));
  3357. + if (this._keyStatus.lastKeyReleased) {
  3358. + this._keyStatus.event = e
  3359. + this.fire(this._keyStatus)
  3360. + }
  3361. + },
  3362. + true,
  3363. + ),
  3364. + )
  3365. +
  3366. + disposables.add(
  3367. + addDisposableListener(
  3368. + window.document.body,
  3369. + "mousedown",
  3370. + () => {
  3371. + this._keyStatus.lastKeyPressed = undefined
  3372. + },
  3373. + true,
  3374. + ),
  3375. + )
  3376. +
  3377. + disposables.add(
  3378. + addDisposableListener(
  3379. + window.document.body,
  3380. + "mouseup",
  3381. + () => {
  3382. + this._keyStatus.lastKeyPressed = undefined
  3383. + },
  3384. + true,
  3385. + ),
  3386. + )
  3387. +
  3388. + disposables.add(
  3389. + addDisposableListener(
  3390. + window.document.body,
  3391. + "mousemove",
  3392. + (e) => {
  3393. + if (e.buttons) {
  3394. + this._keyStatus.lastKeyPressed = undefined
  3395. + }
  3396. + },
  3397. + true,
  3398. + ),
  3399. + )
  3400. - disposables.add(addDisposableListener(window, 'blur', () => {
  3401. - this.resetKeyStatus();
  3402. - }));
  3403. + disposables.add(
  3404. + addDisposableListener(window, "blur", () => {
  3405. + this.resetKeyStatus()
  3406. + }),
  3407. + )
  3408. }
  3409. get keyStatus(): IModifierKeyStatus {
  3410. - return this._keyStatus;
  3411. + return this._keyStatus
  3412. }
  3413. get isModifierPressed(): boolean {
  3414. - return this._keyStatus.altKey || this._keyStatus.ctrlKey || this._keyStatus.metaKey || this._keyStatus.shiftKey;
  3415. + return this._keyStatus.altKey || this._keyStatus.ctrlKey || this._keyStatus.metaKey || this._keyStatus.shiftKey
  3416. }
  3417. /**
  3418. * Allows to explicitly reset the key status based on more knowledge (#109062)
  3419. */
  3420. resetKeyStatus(): void {
  3421. - this.doResetKeyStatus();
  3422. - this.fire(this._keyStatus);
  3423. + this.doResetKeyStatus()
  3424. + this.fire(this._keyStatus)
  3425. }
  3426. private doResetKeyStatus(): void {
  3427. @@ -1959,139 +2178,158 @@ export class ModifierKeyEmitter extends event.Emitter<IModifierKeyStatus> {
  3428. altKey: false,
  3429. shiftKey: false,
  3430. ctrlKey: false,
  3431. - metaKey: false
  3432. - };
  3433. + metaKey: false,
  3434. + }
  3435. }
  3436. static getInstance() {
  3437. if (!ModifierKeyEmitter.instance) {
  3438. - ModifierKeyEmitter.instance = new ModifierKeyEmitter();
  3439. + ModifierKeyEmitter.instance = new ModifierKeyEmitter()
  3440. }
  3441. - return ModifierKeyEmitter.instance;
  3442. + return ModifierKeyEmitter.instance
  3443. }
  3444. override dispose() {
  3445. - super.dispose();
  3446. - this._subscriptions.dispose();
  3447. + super.dispose()
  3448. + this._subscriptions.dispose()
  3449. }
  3450. }
  3451. export function getCookieValue(name: string): string | undefined {
  3452. - const match = document.cookie.match('(^|[^;]+)\\s*' + name + '\\s*=\\s*([^;]+)'); // See https://stackoverflow.com/a/25490531
  3453. + const match = document.cookie.match("(^|[^;]+)\\s*" + name + "\\s*=\\s*([^;]+)") // See https://stackoverflow.com/a/25490531
  3454. - return match ? match.pop() : undefined;
  3455. + return match ? match.pop() : undefined
  3456. }
  3457. export interface IDragAndDropObserverCallbacks {
  3458. - readonly onDragEnter?: (e: DragEvent) => void;
  3459. - readonly onDragLeave?: (e: DragEvent) => void;
  3460. - readonly onDrop?: (e: DragEvent) => void;
  3461. - readonly onDragEnd?: (e: DragEvent) => void;
  3462. - readonly onDragStart?: (e: DragEvent) => void;
  3463. - readonly onDrag?: (e: DragEvent) => void;
  3464. - readonly onDragOver?: (e: DragEvent, dragDuration: number) => void;
  3465. + readonly onDragEnter?: (e: DragEvent) => void
  3466. + readonly onDragLeave?: (e: DragEvent) => void
  3467. + readonly onDrop?: (e: DragEvent) => void
  3468. + readonly onDragEnd?: (e: DragEvent) => void
  3469. + readonly onDragStart?: (e: DragEvent) => void
  3470. + readonly onDrag?: (e: DragEvent) => void
  3471. + readonly onDragOver?: (e: DragEvent, dragDuration: number) => void
  3472. }
  3473. export class DragAndDropObserver extends Disposable {
  3474. -
  3475. // A helper to fix issues with repeated DRAG_ENTER / DRAG_LEAVE
  3476. // calls see https://github.com/microsoft/vscode/issues/14470
  3477. // when the element has child elements where the events are fired
  3478. // repeadedly.
  3479. - private counter: number = 0;
  3480. + private counter: number = 0
  3481. // Allows to measure the duration of the drag operation.
  3482. - private dragStartTime = 0;
  3483. + private dragStartTime = 0
  3484. - constructor(private readonly element: HTMLElement, private readonly callbacks: IDragAndDropObserverCallbacks) {
  3485. - super();
  3486. + constructor(
  3487. + private readonly element: HTMLElement,
  3488. + private readonly callbacks: IDragAndDropObserverCallbacks,
  3489. + ) {
  3490. + super()
  3491. - this.registerListeners();
  3492. + this.registerListeners()
  3493. }
  3494. private registerListeners(): void {
  3495. if (this.callbacks.onDragStart) {
  3496. - this._register(addDisposableListener(this.element, EventType.DRAG_START, (e: DragEvent) => {
  3497. - this.callbacks.onDragStart?.(e);
  3498. - }));
  3499. + this._register(
  3500. + addDisposableListener(this.element, EventType.DRAG_START, (e: DragEvent) => {
  3501. + this.callbacks.onDragStart?.(e)
  3502. + }),
  3503. + )
  3504. }
  3505. if (this.callbacks.onDrag) {
  3506. - this._register(addDisposableListener(this.element, EventType.DRAG, (e: DragEvent) => {
  3507. - this.callbacks.onDrag?.(e);
  3508. - }));
  3509. + this._register(
  3510. + addDisposableListener(this.element, EventType.DRAG, (e: DragEvent) => {
  3511. + this.callbacks.onDrag?.(e)
  3512. + }),
  3513. + )
  3514. }
  3515. - this._register(addDisposableListener(this.element, EventType.DRAG_ENTER, (e: DragEvent) => {
  3516. - this.counter++;
  3517. - this.dragStartTime = e.timeStamp;
  3518. + this._register(
  3519. + addDisposableListener(this.element, EventType.DRAG_ENTER, (e: DragEvent) => {
  3520. + this.counter++
  3521. + this.dragStartTime = e.timeStamp
  3522. - this.callbacks.onDragEnter?.(e);
  3523. - }));
  3524. + this.callbacks.onDragEnter?.(e)
  3525. + }),
  3526. + )
  3527. - this._register(addDisposableListener(this.element, EventType.DRAG_OVER, (e: DragEvent) => {
  3528. - e.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome)
  3529. + this._register(
  3530. + addDisposableListener(this.element, EventType.DRAG_OVER, (e: DragEvent) => {
  3531. + e.preventDefault() // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome)
  3532. - this.callbacks.onDragOver?.(e, e.timeStamp - this.dragStartTime);
  3533. - }));
  3534. + this.callbacks.onDragOver?.(e, e.timeStamp - this.dragStartTime)
  3535. + }),
  3536. + )
  3537. - this._register(addDisposableListener(this.element, EventType.DRAG_LEAVE, (e: DragEvent) => {
  3538. - this.counter--;
  3539. + this._register(
  3540. + addDisposableListener(this.element, EventType.DRAG_LEAVE, (e: DragEvent) => {
  3541. + this.counter--
  3542. - if (this.counter === 0) {
  3543. - this.dragStartTime = 0;
  3544. + if (this.counter === 0) {
  3545. + this.dragStartTime = 0
  3546. - this.callbacks.onDragLeave?.(e);
  3547. - }
  3548. - }));
  3549. + this.callbacks.onDragLeave?.(e)
  3550. + }
  3551. + }),
  3552. + )
  3553. - this._register(addDisposableListener(this.element, EventType.DRAG_END, (e: DragEvent) => {
  3554. - this.counter = 0;
  3555. - this.dragStartTime = 0;
  3556. + this._register(
  3557. + addDisposableListener(this.element, EventType.DRAG_END, (e: DragEvent) => {
  3558. + this.counter = 0
  3559. + this.dragStartTime = 0
  3560. - this.callbacks.onDragEnd?.(e);
  3561. - }));
  3562. + this.callbacks.onDragEnd?.(e)
  3563. + }),
  3564. + )
  3565. - this._register(addDisposableListener(this.element, EventType.DROP, (e: DragEvent) => {
  3566. - this.counter = 0;
  3567. - this.dragStartTime = 0;
  3568. + this._register(
  3569. + addDisposableListener(this.element, EventType.DROP, (e: DragEvent) => {
  3570. + this.counter = 0
  3571. + this.dragStartTime = 0
  3572. - this.callbacks.onDrop?.(e);
  3573. - }));
  3574. + this.callbacks.onDrop?.(e)
  3575. + }),
  3576. + )
  3577. }
  3578. }
  3579. -type HTMLElementAttributeKeys<T> = Partial<{ [K in keyof T]: T[K] extends Function ? never : T[K] extends object ? HTMLElementAttributeKeys<T[K]> : T[K] }>;
  3580. -type ElementAttributes<T> = HTMLElementAttributeKeys<T> & Record<string, any>;
  3581. -type RemoveHTMLElement<T> = T extends HTMLElement ? never : T;
  3582. -type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
  3583. -type ArrayToObj<T extends readonly any[]> = UnionToIntersection<RemoveHTMLElement<T[number]>>;
  3584. -type HHTMLElementTagNameMap = HTMLElementTagNameMap & { '': HTMLDivElement };
  3585. +type HTMLElementAttributeKeys<T> = Partial<{
  3586. + [K in keyof T]: T[K] extends Function ? never : T[K] extends object ? HTMLElementAttributeKeys<T[K]> : T[K]
  3587. +}>
  3588. +type ElementAttributes<T> = HTMLElementAttributeKeys<T> & Record<string, any>
  3589. +type RemoveHTMLElement<T> = T extends HTMLElement ? never : T
  3590. +type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never
  3591. +type ArrayToObj<T extends readonly any[]> = UnionToIntersection<RemoveHTMLElement<T[number]>>
  3592. +type HHTMLElementTagNameMap = HTMLElementTagNameMap & { "": HTMLDivElement }
  3593. type TagToElement<T> = T extends `${infer TStart}#${string}`
  3594. ? TStart extends keyof HHTMLElementTagNameMap
  3595. - ? HHTMLElementTagNameMap[TStart]
  3596. - : HTMLElement
  3597. + ? HHTMLElementTagNameMap[TStart]
  3598. + : HTMLElement
  3599. : T extends `${infer TStart}.${string}`
  3600. - ? TStart extends keyof HHTMLElementTagNameMap
  3601. - ? HHTMLElementTagNameMap[TStart]
  3602. - : HTMLElement
  3603. - : T extends keyof HTMLElementTagNameMap
  3604. - ? HTMLElementTagNameMap[T]
  3605. - : HTMLElement;
  3606. + ? TStart extends keyof HHTMLElementTagNameMap
  3607. + ? HHTMLElementTagNameMap[TStart]
  3608. + : HTMLElement
  3609. + : T extends keyof HTMLElementTagNameMap
  3610. + ? HTMLElementTagNameMap[T]
  3611. + : HTMLElement
  3612. type TagToElementAndId<TTag> = TTag extends `${infer TTag}@${infer TId}`
  3613. ? { element: TagToElement<TTag>; id: TId }
  3614. - : { element: TagToElement<TTag>; id: 'root' };
  3615. + : { element: TagToElement<TTag>; id: "root" }
  3616. -type TagToRecord<TTag> = TagToElementAndId<TTag> extends { element: infer TElement; id: infer TId }
  3617. - ? Record<(TId extends string ? TId : never) | 'root', TElement>
  3618. - : never;
  3619. +type TagToRecord<TTag> =
  3620. + TagToElementAndId<TTag> extends { element: infer TElement; id: infer TId }
  3621. + ? Record<(TId extends string ? TId : never) | "root", TElement>
  3622. + : never
  3623. -type Child = HTMLElement | string | Record<string, HTMLElement>;
  3624. +type Child = HTMLElement | string | Record<string, HTMLElement>
  3625. -const H_REGEX = /(?<tag>[\w\-]+)?(?:#(?<id>[\w\-]+))?(?<class>(?:\.(?:[\w\-]+))*)(?:@(?<name>(?:[\w\_])+))?/;
  3626. +const H_REGEX = /(?<tag>[\w\-]+)?(?:#(?<id>[\w\-]+))?(?<class>(?:\.(?:[\w\-]+))*)(?:@(?<name>(?:[\w\_])+))?/
  3627. /**
  3628. * A helper function to create nested dom nodes.
  3629. @@ -2107,249 +2345,283 @@ const H_REGEX = /(?<tag>[\w\-]+)?(?:#(?<id>[\w\-]+))?(?<class>(?:\.(?:[\w\-]+))*
  3630. * ]);
  3631. * const editor = createEditor(elements.editor);
  3632. * ```
  3633. -*/
  3634. -export function h<TTag extends string>
  3635. - (tag: TTag):
  3636. - TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
  3637. -
  3638. -export function h<TTag extends string, T extends Child[]>
  3639. - (tag: TTag, children: [...T]):
  3640. - (ArrayToObj<T> & TagToRecord<TTag>) extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
  3641. -
  3642. -export function h<TTag extends string>
  3643. - (tag: TTag, attributes: Partial<ElementAttributes<TagToElement<TTag>>>):
  3644. - TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
  3645. -
  3646. -export function h<TTag extends string, T extends Child[]>
  3647. - (tag: TTag, attributes: Partial<ElementAttributes<TagToElement<TTag>>>, children: [...T]):
  3648. - (ArrayToObj<T> & TagToRecord<TTag>) extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
  3649. -
  3650. -export function h(tag: string, ...args: [] | [attributes: { $: string } & Partial<ElementAttributes<HTMLElement>> | Record<string, any>, children?: any[]] | [children: any[]]): Record<string, HTMLElement> {
  3651. - let attributes: { $?: string } & Partial<ElementAttributes<HTMLElement>>;
  3652. - let children: (Record<string, HTMLElement> | HTMLElement)[] | undefined;
  3653. + */
  3654. +export function h<TTag extends string>(
  3655. + tag: TTag,
  3656. +): TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never
  3657. +
  3658. +export function h<TTag extends string, T extends Child[]>(
  3659. + tag: TTag,
  3660. + children: [...T],
  3661. +): ArrayToObj<T> & TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never
  3662. +
  3663. +export function h<TTag extends string>(
  3664. + tag: TTag,
  3665. + attributes: Partial<ElementAttributes<TagToElement<TTag>>>,
  3666. +): TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never
  3667. +
  3668. +export function h<TTag extends string, T extends Child[]>(
  3669. + tag: TTag,
  3670. + attributes: Partial<ElementAttributes<TagToElement<TTag>>>,
  3671. + children: [...T],
  3672. +): ArrayToObj<T> & TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never
  3673. +
  3674. +export function h(
  3675. + tag: string,
  3676. + ...args:
  3677. + | []
  3678. + | [
  3679. + attributes: ({ $: string } & Partial<ElementAttributes<HTMLElement>>) | Record<string, any>,
  3680. + children?: any[],
  3681. + ]
  3682. + | [children: any[]]
  3683. +): Record<string, HTMLElement> {
  3684. + let attributes: { $?: string } & Partial<ElementAttributes<HTMLElement>>
  3685. + let children: (Record<string, HTMLElement> | HTMLElement)[] | undefined
  3686. if (Array.isArray(args[0])) {
  3687. - attributes = {};
  3688. - children = args[0];
  3689. + attributes = {}
  3690. + children = args[0]
  3691. } else {
  3692. - attributes = args[0] as any || {};
  3693. - children = args[1];
  3694. + attributes = (args[0] as any) || {}
  3695. + children = args[1]
  3696. }
  3697. - const match = H_REGEX.exec(tag);
  3698. + const match = H_REGEX.exec(tag)
  3699. if (!match || !match.groups) {
  3700. - throw new Error('Bad use of h');
  3701. + throw new Error("Bad use of h")
  3702. }
  3703. - const tagName = match.groups['tag'] || 'div';
  3704. - const el = document.createElement(tagName);
  3705. + const tagName = match.groups["tag"] || "div"
  3706. + const el = document.createElement(tagName)
  3707. - if (match.groups['id']) {
  3708. - el.id = match.groups['id'];
  3709. + if (match.groups["id"]) {
  3710. + el.id = match.groups["id"]
  3711. }
  3712. - const classNames = [];
  3713. - if (match.groups['class']) {
  3714. - for (const className of match.groups['class'].split('.')) {
  3715. - if (className !== '') {
  3716. - classNames.push(className);
  3717. + const classNames = []
  3718. + if (match.groups["class"]) {
  3719. + for (const className of match.groups["class"].split(".")) {
  3720. + if (className !== "") {
  3721. + classNames.push(className)
  3722. }
  3723. }
  3724. }
  3725. if (attributes.className !== undefined) {
  3726. - for (const className of attributes.className.split('.')) {
  3727. - if (className !== '') {
  3728. - classNames.push(className);
  3729. + for (const className of attributes.className.split(".")) {
  3730. + if (className !== "") {
  3731. + classNames.push(className)
  3732. }
  3733. }
  3734. }
  3735. if (classNames.length > 0) {
  3736. - el.className = classNames.join(' ');
  3737. + el.className = classNames.join(" ")
  3738. }
  3739. - const result: Record<string, HTMLElement> = {};
  3740. + const result: Record<string, HTMLElement> = {}
  3741. - if (match.groups['name']) {
  3742. - result[match.groups['name']] = el;
  3743. + if (match.groups["name"]) {
  3744. + result[match.groups["name"]] = el
  3745. }
  3746. if (children) {
  3747. for (const c of children) {
  3748. if (isHTMLElement(c)) {
  3749. - el.appendChild(c);
  3750. - } else if (typeof c === 'string') {
  3751. - el.append(c);
  3752. - } else if ('root' in c) {
  3753. - Object.assign(result, c);
  3754. - el.appendChild(c.root);
  3755. + el.appendChild(c)
  3756. + } else if (typeof c === "string") {
  3757. + el.append(c)
  3758. + } else if ("root" in c) {
  3759. + Object.assign(result, c)
  3760. + el.appendChild(c.root)
  3761. }
  3762. }
  3763. }
  3764. for (const [key, value] of Object.entries(attributes)) {
  3765. - if (key === 'className') {
  3766. - continue;
  3767. - } else if (key === 'style') {
  3768. + if (key === "className") {
  3769. + continue
  3770. + } else if (key === "style") {
  3771. for (const [cssKey, cssValue] of Object.entries(value)) {
  3772. el.style.setProperty(
  3773. camelCaseToHyphenCase(cssKey),
  3774. - typeof cssValue === 'number' ? cssValue + 'px' : '' + cssValue
  3775. - );
  3776. + typeof cssValue === "number" ? cssValue + "px" : "" + cssValue,
  3777. + )
  3778. }
  3779. - } else if (key === 'tabIndex') {
  3780. - el.tabIndex = value;
  3781. + } else if (key === "tabIndex") {
  3782. + el.tabIndex = value
  3783. } else {
  3784. - el.setAttribute(camelCaseToHyphenCase(key), value.toString());
  3785. + el.setAttribute(camelCaseToHyphenCase(key), value.toString())
  3786. }
  3787. }
  3788. - result['root'] = el;
  3789. + result["root"] = el
  3790. - return result;
  3791. + return result
  3792. }
  3793. /** @deprecated This is a duplication of the h function. Needs cleanup. */
  3794. -export function svgElem<TTag extends string>
  3795. - (tag: TTag):
  3796. - TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
  3797. +export function svgElem<TTag extends string>(
  3798. + tag: TTag,
  3799. +): TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never
  3800. /** @deprecated This is a duplication of the h function. Needs cleanup. */
  3801. -export function svgElem<TTag extends string, T extends Child[]>
  3802. - (tag: TTag, children: [...T]):
  3803. - (ArrayToObj<T> & TagToRecord<TTag>) extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
  3804. +export function svgElem<TTag extends string, T extends Child[]>(
  3805. + tag: TTag,
  3806. + children: [...T],
  3807. +): ArrayToObj<T> & TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never
  3808. /** @deprecated This is a duplication of the h function. Needs cleanup. */
  3809. -export function svgElem<TTag extends string>
  3810. - (tag: TTag, attributes: Partial<ElementAttributes<TagToElement<TTag>>>):
  3811. - TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
  3812. +export function svgElem<TTag extends string>(
  3813. + tag: TTag,
  3814. + attributes: Partial<ElementAttributes<TagToElement<TTag>>>,
  3815. +): TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never
  3816. /** @deprecated This is a duplication of the h function. Needs cleanup. */
  3817. -export function svgElem<TTag extends string, T extends Child[]>
  3818. - (tag: TTag, attributes: Partial<ElementAttributes<TagToElement<TTag>>>, children: [...T]):
  3819. - (ArrayToObj<T> & TagToRecord<TTag>) extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
  3820. +export function svgElem<TTag extends string, T extends Child[]>(
  3821. + tag: TTag,
  3822. + attributes: Partial<ElementAttributes<TagToElement<TTag>>>,
  3823. + children: [...T],
  3824. +): ArrayToObj<T> & TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never
  3825. /** @deprecated This is a duplication of the h function. Needs cleanup. */
  3826. -export function svgElem(tag: string, ...args: [] | [attributes: { $: string } & Partial<ElementAttributes<HTMLElement>> | Record<string, any>, children?: any[]] | [children: any[]]): Record<string, HTMLElement> {
  3827. - let attributes: { $?: string } & Partial<ElementAttributes<HTMLElement>>;
  3828. - let children: (Record<string, HTMLElement> | HTMLElement)[] | undefined;
  3829. +export function svgElem(
  3830. + tag: string,
  3831. + ...args:
  3832. + | []
  3833. + | [
  3834. + attributes: ({ $: string } & Partial<ElementAttributes<HTMLElement>>) | Record<string, any>,
  3835. + children?: any[],
  3836. + ]
  3837. + | [children: any[]]
  3838. +): Record<string, HTMLElement> {
  3839. + let attributes: { $?: string } & Partial<ElementAttributes<HTMLElement>>
  3840. + let children: (Record<string, HTMLElement> | HTMLElement)[] | undefined
  3841. if (Array.isArray(args[0])) {
  3842. - attributes = {};
  3843. - children = args[0];
  3844. + attributes = {}
  3845. + children = args[0]
  3846. } else {
  3847. - attributes = args[0] as any || {};
  3848. - children = args[1];
  3849. + attributes = (args[0] as any) || {}
  3850. + children = args[1]
  3851. }
  3852. - const match = H_REGEX.exec(tag);
  3853. + const match = H_REGEX.exec(tag)
  3854. if (!match || !match.groups) {
  3855. - throw new Error('Bad use of h');
  3856. + throw new Error("Bad use of h")
  3857. }
  3858. - const tagName = match.groups['tag'] || 'div';
  3859. - const el = document.createElementNS('http://www.w3.org/2000/svg', tagName) as any as HTMLElement;
  3860. + const tagName = match.groups["tag"] || "div"
  3861. + const el = document.createElementNS("http://www.w3.org/2000/svg", tagName) as any as HTMLElement
  3862. - if (match.groups['id']) {
  3863. - el.id = match.groups['id'];
  3864. + if (match.groups["id"]) {
  3865. + el.id = match.groups["id"]
  3866. }
  3867. - const classNames = [];
  3868. - if (match.groups['class']) {
  3869. - for (const className of match.groups['class'].split('.')) {
  3870. - if (className !== '') {
  3871. - classNames.push(className);
  3872. + const classNames = []
  3873. + if (match.groups["class"]) {
  3874. + for (const className of match.groups["class"].split(".")) {
  3875. + if (className !== "") {
  3876. + classNames.push(className)
  3877. }
  3878. }
  3879. }
  3880. if (attributes.className !== undefined) {
  3881. - for (const className of attributes.className.split('.')) {
  3882. - if (className !== '') {
  3883. - classNames.push(className);
  3884. + for (const className of attributes.className.split(".")) {
  3885. + if (className !== "") {
  3886. + classNames.push(className)
  3887. }
  3888. }
  3889. }
  3890. if (classNames.length > 0) {
  3891. - el.className = classNames.join(' ');
  3892. + el.className = classNames.join(" ")
  3893. }
  3894. - const result: Record<string, HTMLElement> = {};
  3895. + const result: Record<string, HTMLElement> = {}
  3896. - if (match.groups['name']) {
  3897. - result[match.groups['name']] = el;
  3898. + if (match.groups["name"]) {
  3899. + result[match.groups["name"]] = el
  3900. }
  3901. if (children) {
  3902. for (const c of children) {
  3903. if (isHTMLElement(c)) {
  3904. - el.appendChild(c);
  3905. - } else if (typeof c === 'string') {
  3906. - el.append(c);
  3907. - } else if ('root' in c) {
  3908. - Object.assign(result, c);
  3909. - el.appendChild(c.root);
  3910. + el.appendChild(c)
  3911. + } else if (typeof c === "string") {
  3912. + el.append(c)
  3913. + } else if ("root" in c) {
  3914. + Object.assign(result, c)
  3915. + el.appendChild(c.root)
  3916. }
  3917. }
  3918. }
  3919. for (const [key, value] of Object.entries(attributes)) {
  3920. - if (key === 'className') {
  3921. - continue;
  3922. - } else if (key === 'style') {
  3923. + if (key === "className") {
  3924. + continue
  3925. + } else if (key === "style") {
  3926. for (const [cssKey, cssValue] of Object.entries(value)) {
  3927. el.style.setProperty(
  3928. camelCaseToHyphenCase(cssKey),
  3929. - typeof cssValue === 'number' ? cssValue + 'px' : '' + cssValue
  3930. - );
  3931. + typeof cssValue === "number" ? cssValue + "px" : "" + cssValue,
  3932. + )
  3933. }
  3934. - } else if (key === 'tabIndex') {
  3935. - el.tabIndex = value;
  3936. + } else if (key === "tabIndex") {
  3937. + el.tabIndex = value
  3938. } else {
  3939. - el.setAttribute(camelCaseToHyphenCase(key), value.toString());
  3940. + el.setAttribute(camelCaseToHyphenCase(key), value.toString())
  3941. }
  3942. }
  3943. - result['root'] = el;
  3944. + result["root"] = el
  3945. - return result;
  3946. + return result
  3947. }
  3948. function camelCaseToHyphenCase(str: string) {
  3949. - return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
  3950. + return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()
  3951. }
  3952. export function copyAttributes(from: Element, to: Element, filter?: string[]): void {
  3953. for (const { name, value } of from.attributes) {
  3954. if (!filter || filter.includes(name)) {
  3955. - to.setAttribute(name, value);
  3956. + to.setAttribute(name, value)
  3957. }
  3958. }
  3959. }
  3960. function copyAttribute(from: Element, to: Element, name: string): void {
  3961. - const value = from.getAttribute(name);
  3962. + const value = from.getAttribute(name)
  3963. if (value) {
  3964. - to.setAttribute(name, value);
  3965. + to.setAttribute(name, value)
  3966. } else {
  3967. - to.removeAttribute(name);
  3968. + to.removeAttribute(name)
  3969. }
  3970. }
  3971. export function trackAttributes(from: Element, to: Element, filter?: string[]): IDisposable {
  3972. - copyAttributes(from, to, filter);
  3973. + copyAttributes(from, to, filter)
  3974. - const disposables = new DisposableStore();
  3975. + const disposables = new DisposableStore()
  3976. - disposables.add(sharedMutationObserver.observe(from, disposables, { attributes: true, attributeFilter: filter })(mutations => {
  3977. - for (const mutation of mutations) {
  3978. - if (mutation.type === 'attributes' && mutation.attributeName) {
  3979. - copyAttribute(from, to, mutation.attributeName);
  3980. - }
  3981. - }
  3982. - }));
  3983. + disposables.add(
  3984. + sharedMutationObserver.observe(from, disposables, { attributes: true, attributeFilter: filter })(
  3985. + (mutations) => {
  3986. + for (const mutation of mutations) {
  3987. + if (mutation.type === "attributes" && mutation.attributeName) {
  3988. + copyAttribute(from, to, mutation.attributeName)
  3989. + }
  3990. + }
  3991. + },
  3992. + ),
  3993. + )
  3994. - return disposables;
  3995. + return disposables
  3996. }
  3997. export function isEditableElement(element: Element): boolean {
  3998. - return element.tagName.toLowerCase() === 'input' || element.tagName.toLowerCase() === 'textarea' || isHTMLElement(element) && !!element.editContext;
  3999. + return (
  4000. + element.tagName.toLowerCase() === "input" ||
  4001. + element.tagName.toLowerCase() === "textarea" ||
  4002. + (isHTMLElement(element) && !!element.editContext)
  4003. + )
  4004. }
  4005. /**
  4006. @@ -2358,40 +2630,40 @@ export function isEditableElement(element: Element): boolean {
  4007. */
  4008. export class SafeTriangle {
  4009. // 4 points (x, y), 8 length
  4010. - private points = new Int16Array(8);
  4011. + private points = new Int16Array(8)
  4012. constructor(
  4013. private readonly originX: number,
  4014. private readonly originY: number,
  4015. - target: HTMLElement
  4016. + target: HTMLElement,
  4017. ) {
  4018. - const { top, left, right, bottom } = target.getBoundingClientRect();
  4019. - const t = this.points;
  4020. - let i = 0;
  4021. + const { top, left, right, bottom } = target.getBoundingClientRect()
  4022. + const t = this.points
  4023. + let i = 0
  4024. - t[i++] = left;
  4025. - t[i++] = top;
  4026. + t[i++] = left
  4027. + t[i++] = top
  4028. - t[i++] = right;
  4029. - t[i++] = top;
  4030. + t[i++] = right
  4031. + t[i++] = top
  4032. - t[i++] = left;
  4033. - t[i++] = bottom;
  4034. + t[i++] = left
  4035. + t[i++] = bottom
  4036. - t[i++] = right;
  4037. - t[i++] = bottom;
  4038. + t[i++] = right
  4039. + t[i++] = bottom
  4040. }
  4041. public contains(x: number, y: number) {
  4042. - const { points, originX, originY } = this;
  4043. + const { points, originX, originY } = this
  4044. for (let i = 0; i < 4; i++) {
  4045. - const p1 = 2 * i;
  4046. - const p2 = 2 * ((i + 1) % 4);
  4047. + const p1 = 2 * i
  4048. + const p2 = 2 * ((i + 1) % 4)
  4049. if (isPointWithinTriangle(x, y, originX, originY, points[p1], points[p1 + 1], points[p2], points[p2 + 1])) {
  4050. - return true;
  4051. + return true
  4052. }
  4053. }
  4054. - return false;
  4055. + return false
  4056. }
  4057. }
  4058. diff --git a/src/vs/base/common/uri.ts b/src/vs/base/common/uri.ts
  4059. index 73a3aa6cd49..404070f038f 100644
  4060. --- a/src/vs/base/common/uri.ts
  4061. +++ b/src/vs/base/common/uri.ts
  4062. @@ -21,6 +21,7 @@ function _validateUri(ret: URI, _strict?: boolean): void {
  4063. // scheme, https://tools.ietf.org/html/rfc3986#section-3.1
  4064. // ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
  4065. + // console.log('validate uri', ret.scheme);
  4066. if (ret.scheme && !_schemePattern.test(ret.scheme)) {
  4067. throw new Error('[UriError]: Scheme contains illegal characters.');
  4068. }
  4069. diff --git a/src/vs/base/parts/ipc/common/ipc.net.ts b/src/vs/base/parts/ipc/common/ipc.net.ts
  4070. index 1bc63ba6878..b31f1260a5f 100644
  4071. --- a/src/vs/base/parts/ipc/common/ipc.net.ts
  4072. +++ b/src/vs/base/parts/ipc/common/ipc.net.ts
  4073. @@ -3,6 +3,9 @@
  4074. * Licensed under the MIT License. See License.txt in the project root for license information.
  4075. *--------------------------------------------------------------------------------------------*/
  4076. +import { fileLoggerGlobal } from '../../../../../../../src/extension.js';
  4077. +import { FileRPCProtocolLogger } from '../../../../workbench/services/extensions/common/fileRPCProtocolLogger.js';
  4078. +import { RequestInitiator } from '../../../../workbench/services/extensions/common/rpcProtocol.js';
  4079. import { VSBuffer } from '../../../common/buffer.js';
  4080. import { Emitter, Event } from '../../../common/event.js';
  4081. import { Disposable, DisposableStore, IDisposable } from '../../../common/lifecycle.js';
  4082. @@ -281,7 +284,7 @@ function protocolMessageTypeToString(messageType: ProtocolMessageType) {
  4083. }
  4084. export const enum ProtocolConstants {
  4085. - HeaderLength = 13,
  4086. +HeaderLength = 13,
  4087. /**
  4088. * Send an Acknowledge message at most 2 seconds later...
  4089. */
  4090. @@ -353,13 +356,14 @@ class ProtocolReader extends Disposable {
  4091. public acceptChunk(data: VSBuffer | null): void {
  4092. if (!data || data.byteLength === 0) {
  4093. + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'Accept chunk: empty buffer');
  4094. return;
  4095. }
  4096. + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'Accept chunk: ' + data.byteLength + ', read head: ' + this._state.readHead + ', read len: ' + this._state.readLen);
  4097. this.lastReadTime = Date.now();
  4098. this._incomingData.acceptChunk(data);
  4099. -
  4100. while (this._incomingData.byteLength >= this._state.readLen) {
  4101. const buff = this._incomingData.read(this._state.readLen);
  4102. @@ -373,6 +377,7 @@ class ProtocolReader extends Disposable {
  4103. this._state.messageType = buff.readUInt8(0);
  4104. this._state.id = buff.readUInt32BE(1);
  4105. this._state.ack = buff.readUInt32BE(5);
  4106. + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'Protocol header read: ' + this._state.id);
  4107. this._socket.traceSocketEvent(SocketDiagnosticsEventType.ProtocolHeaderRead, { messageType: protocolMessageTypeToString(this._state.messageType), id: this._state.id, ack: this._state.ack, messageSize: this._state.readLen });
  4108. @@ -388,6 +393,7 @@ class ProtocolReader extends Disposable {
  4109. this._state.messageType = ProtocolMessageType.None;
  4110. this._state.id = 0;
  4111. this._state.ack = 0;
  4112. + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'Protocol message read: ' + id + ', type: ' + messageType + ', ack: ' + ack);
  4113. this._socket.traceSocketEvent(SocketDiagnosticsEventType.ProtocolMessageRead, buff);
  4114. @@ -832,6 +838,7 @@ export class PersistentProtocol implements IMessagePassingProtocol {
  4115. private _socketReader: ProtocolReader;
  4116. // eslint-disable-next-line local/code-no-potentially-unsafe-disposables
  4117. private _socketDisposables: DisposableStore;
  4118. + private _fileLogger: FileRPCProtocolLogger;
  4119. private readonly _loadEstimator: ILoadEstimator;
  4120. private readonly _shouldSendKeepAlive: boolean;
  4121. @@ -878,7 +885,7 @@ export class PersistentProtocol implements IMessagePassingProtocol {
  4122. this._socketReader = this._socketDisposables.add(new ProtocolReader(this._socket));
  4123. this._socketDisposables.add(this._socketReader.onMessage(msg => this._receiveMessage(msg)));
  4124. this._socketDisposables.add(this._socket.onClose(e => this._onSocketClose.fire(e)));
  4125. -
  4126. + this._fileLogger = new FileRPCProtocolLogger('PersistentProtocol');
  4127. if (opts.initialChunk) {
  4128. this._socketReader.acceptChunk(opts.initialChunk);
  4129. }
  4130. @@ -944,6 +951,7 @@ export class PersistentProtocol implements IMessagePassingProtocol {
  4131. }
  4132. public beginAcceptReconnection(socket: ISocket, initialDataChunk: VSBuffer | null): void {
  4133. + this._fileLogger.logIncoming(0, 0, RequestInitiator.LocalSide, 'Begin accept reconnection');
  4134. this._isReconnecting = true;
  4135. this._socketDisposables.dispose();
  4136. @@ -966,6 +974,7 @@ export class PersistentProtocol implements IMessagePassingProtocol {
  4137. }
  4138. public endAcceptReconnection(): void {
  4139. + this._fileLogger.logIncoming(0, 0, RequestInitiator.LocalSide, 'End accept reconnection');
  4140. this._isReconnecting = false;
  4141. // After a reconnection, let the other party know (again) which messages have been received.
  4142. @@ -987,6 +996,7 @@ export class PersistentProtocol implements IMessagePassingProtocol {
  4143. }
  4144. private _receiveMessage(msg: ProtocolMessage): void {
  4145. + this._fileLogger.logIncoming(0, 0, RequestInitiator.LocalSide, 'Receive message: ' + msg.type + ', id: ' + msg.id + ', ack: ' + msg.ack + ', data: ' + msg.data.byteLength + ', _incomingMsgId: ' + this._incomingMsgId);
  4146. if (msg.ack > this._outgoingAckId) {
  4147. this._outgoingAckId = msg.ack;
  4148. do {
  4149. diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts
  4150. index 79a1112b410..cb4f3bce86d 100644
  4151. --- a/src/vs/workbench/api/common/extHost.api.impl.ts
  4152. +++ b/src/vs/workbench/api/common/extHost.api.impl.ts
  4153. @@ -1241,14 +1241,14 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
  4154. checkProposedApiEnabled(extension, 'canonicalUriProvider');
  4155. return extHostWorkspace.provideCanonicalUri(uri, options, token);
  4156. },
  4157. - decode(content: Uint8Array, uri: vscode.Uri | undefined, options?: { encoding: string }) {
  4158. + decode: function(content: Uint8Array): Thenable<string> {
  4159. checkProposedApiEnabled(extension, 'textDocumentEncoding');
  4160. - return extHostWorkspace.decode(content, uri, options);
  4161. + return extHostWorkspace.decode(content, undefined, undefined);
  4162. },
  4163. - encode(content: string, uri: vscode.Uri | undefined, options?: { encoding: string }) {
  4164. + encode: function(content: string): Thenable<Uint8Array> {
  4165. checkProposedApiEnabled(extension, 'textDocumentEncoding');
  4166. - return extHostWorkspace.encode(content, uri, options);
  4167. - }
  4168. + return extHostWorkspace.encode(content, undefined, undefined);
  4169. + },
  4170. };
  4171. // namespace: scm
  4172. @@ -1837,3 +1837,4 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
  4173. };
  4174. };
  4175. }
  4176. +
  4177. diff --git a/src/vs/workbench/api/common/extHostConfiguration.ts b/src/vs/workbench/api/common/extHostConfiguration.ts
  4178. index f0d9124a0da..943bda43fe3 100644
  4179. --- a/src/vs/workbench/api/common/extHostConfiguration.ts
  4180. +++ b/src/vs/workbench/api/common/extHostConfiguration.ts
  4181. @@ -159,6 +159,7 @@ export class ExtHostConfigProvider {
  4182. }
  4183. getConfiguration(section?: string, scope?: vscode.ConfigurationScope | null, extensionDescription?: IExtensionDescription): vscode.WorkspaceConfiguration {
  4184. + console.log('getConfiguration', section, scope, extensionDescription);
  4185. const overrides = scopeToOverrides(scope) || {};
  4186. const config = this._toReadonlyValue(this._configuration.getValue(section, overrides, this._extHostWorkspace.workspace));
  4187. diff --git a/src/vs/workbench/api/common/extHostExtensionActivator.ts b/src/vs/workbench/api/common/extHostExtensionActivator.ts
  4188. index 20f8efbfdbd..ad10b82ab40 100644
  4189. --- a/src/vs/workbench/api/common/extHostExtensionActivator.ts
  4190. +++ b/src/vs/workbench/api/common/extHostExtensionActivator.ts
  4191. @@ -11,6 +11,8 @@ import { ExtensionIdentifier, ExtensionIdentifierMap } from '../../../platform/e
  4192. import { ExtensionActivationReason, MissingExtensionDependency } from '../../services/extensions/common/extensions.js';
  4193. import { ILogService } from '../../../platform/log/common/log.js';
  4194. import { Barrier } from '../../../base/common/async.js';
  4195. +import { fileLoggerGlobal } from '../../../../../../src/extension.js';
  4196. +import { RequestInitiator } from '../../services/extensions/common/rpcProtocol.js';
  4197. /**
  4198. * Represents the source code (module) of an extension.
  4199. @@ -229,7 +231,9 @@ export class ExtensionsActivator implements IDisposable {
  4200. }
  4201. public activateById(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void> {
  4202. + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'activateById start: ' + extensionId.value);
  4203. const desc = this._registry.getExtensionDescription(extensionId);
  4204. + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'activateById desc: ' + desc);
  4205. if (!desc) {
  4206. throw new Error(`Extension '${extensionId.value}' is not known`);
  4207. }
  4208. diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts
  4209. index 03aabb46045..9d85ddf4d40 100644
  4210. --- a/src/vs/workbench/api/common/extHostExtensionService.ts
  4211. +++ b/src/vs/workbench/api/common/extHostExtensionService.ts
  4212. @@ -48,6 +48,8 @@ import { StopWatch } from '../../../base/common/stopwatch.js';
  4213. import { isCI, setTimeout0 } from '../../../base/common/platform.js';
  4214. import { IExtHostManagedSockets } from './extHostManagedSockets.js';
  4215. import { Dto } from '../../services/extensions/common/proxyIdentifier.js';
  4216. +import { fileLoggerGlobal } from '../../../../../../src/extension.js';
  4217. +import { RequestInitiator } from '../../services/extensions/common/rpcProtocol.js';
  4218. interface ITestRunner {
  4219. /** Old test runner API, as exported from `vscode/lib/testrunner` */
  4220. @@ -298,6 +300,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
  4221. }
  4222. private _activateByEvent(activationEvent: string, startup: boolean): Promise<void> {
  4223. + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, '_activateByEvent: ' + activationEvent);
  4224. return this._activator.activateByEvent(activationEvent, startup);
  4225. }
  4226. @@ -647,15 +650,19 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
  4227. }
  4228. private _activateAllStartupFinished(): void {
  4229. + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'activateAllStartupFinished start');
  4230. // startup is considered finished
  4231. this._mainThreadExtensionsProxy.$setPerformanceMarks(performance.getMarks());
  4232. this._extHostConfiguration.getConfigProvider().then((configProvider) => {
  4233. + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'activateAllStartupFinished getConfigProvider');
  4234. const shouldDeferActivation = configProvider.getConfiguration('extensions.experimental').get<boolean>('deferredStartupFinishedActivation');
  4235. const allExtensionDescriptions = this._myRegistry.getAllExtensionDescriptions();
  4236. if (shouldDeferActivation) {
  4237. + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'activateAllStartupFinished shouldDeferActivation');
  4238. this._activateAllStartupFinishedDeferred(allExtensionDescriptions);
  4239. } else {
  4240. + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'activateAllStartupFinished !shouldDeferActivation');
  4241. for (const desc of allExtensionDescriptions) {
  4242. if (desc.activationEvents) {
  4243. for (const activationEvent of desc.activationEvents) {
  4244. @@ -671,6 +678,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
  4245. // Handle "eager" activation extensions
  4246. private _handleEagerExtensions(): Promise<void> {
  4247. + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'handleEagerExtensions start');
  4248. const starActivation = this._activateByEvent('*', true).then(undefined, (err) => {
  4249. this._logService.error(err);
  4250. });
  4251. @@ -689,6 +697,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
  4252. }
  4253. private _handleWorkspaceContainsEagerExtensions(folders: ReadonlyArray<vscode.WorkspaceFolder>): Promise<void> {
  4254. + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'handleWorkspaceContainsEagerExtensions start: ' + folders.length);
  4255. if (folders.length === 0) {
  4256. return Promise.resolve(undefined);
  4257. }
  4258. @@ -697,7 +706,9 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
  4259. this._myRegistry.getAllExtensionDescriptions().map((desc) => {
  4260. return this._handleWorkspaceContainsEagerExtension(folders, desc);
  4261. })
  4262. - ).then(() => { });
  4263. + ).then(() => {
  4264. + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'handleWorkspaceContainsEagerExtensions end');
  4265. + });
  4266. }
  4267. private async _handleWorkspaceContainsEagerExtension(folders: ReadonlyArray<vscode.WorkspaceFolder>, desc: IExtensionDescription): Promise<void> {
  4268. @@ -726,6 +737,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
  4269. }
  4270. private async _handleRemoteResolverEagerExtensions(): Promise<void> {
  4271. + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'handleRemoteResolverEagerExtensions start');
  4272. if (this._initData.remote.authority) {
  4273. return this._activateByEvent(`onResolveRemoteAuthority:${this._initData.remote.authority}`, false);
  4274. }
  4275. @@ -803,7 +815,9 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
  4276. }
  4277. private _startExtensionHost(): Promise<void> {
  4278. + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'startExtensionHost start');
  4279. if (this._started) {
  4280. + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'Extension host is already started!');
  4281. throw new Error(`Extension host is already started!`);
  4282. }
  4283. this._started = true;
  4284. @@ -1036,6 +1050,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
  4285. }
  4286. public async $activate(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<boolean> {
  4287. + console.log('activate', extensionId, reason);
  4288. await this._readyToRunExtensions.wait();
  4289. if (!this._myRegistry.getExtensionDescription(extensionId)) {
  4290. // unknown extension => ignore
  4291. diff --git a/src/vs/workbench/api/common/extHostWebview.ts b/src/vs/workbench/api/common/extHostWebview.ts
  4292. index 435df4b03fc..1b85d76d832 100644
  4293. --- a/src/vs/workbench/api/common/extHostWebview.ts
  4294. +++ b/src/vs/workbench/api/common/extHostWebview.ts
  4295. @@ -222,6 +222,7 @@ export class ExtHostWebviews extends Disposable implements extHostProtocol.ExtHo
  4296. jsonMessage: string,
  4297. buffers: SerializableObjectWithBuffers<VSBuffer[]>
  4298. ): void {
  4299. + console.log('onMessage', handle, jsonMessage, buffers);
  4300. const webview = this.getWebview(handle);
  4301. if (webview) {
  4302. const { message } = deserializeWebviewMessage(jsonMessage, buffers.value);
  4303. diff --git a/src/vs/workbench/api/common/extHostWebviewView.ts b/src/vs/workbench/api/common/extHostWebviewView.ts
  4304. index 4696f33c5fa..e30033615aa 100644
  4305. --- a/src/vs/workbench/api/common/extHostWebviewView.ts
  4306. +++ b/src/vs/workbench/api/common/extHostWebviewView.ts
  4307. @@ -12,6 +12,8 @@ import { ViewBadge } from './extHostTypeConverters.js';
  4308. import type * as vscode from 'vscode';
  4309. import * as extHostProtocol from './extHost.protocol.js';
  4310. import * as extHostTypes from './extHostTypes.js';
  4311. +import { fileLoggerGlobal } from '../../../../../../src/extension.js';
  4312. +import { RequestInitiator } from '../../services/extensions/common/rpcProtocol.js';
  4313. /* eslint-disable local/code-no-native-private */
  4314. @@ -162,6 +164,7 @@ export class ExtHostWebviewViews implements extHostProtocol.ExtHostWebviewViewsS
  4315. retainContextWhenHidden?: boolean;
  4316. },
  4317. ): vscode.Disposable {
  4318. + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'registerWebviewViewProvider start: ' + viewType);
  4319. if (this._viewProviders.has(viewType)) {
  4320. throw new Error(`View provider for '${viewType}' already registered`);
  4321. }
  4322. @@ -185,6 +188,8 @@ export class ExtHostWebviewViews implements extHostProtocol.ExtHostWebviewViewsS
  4323. state: any,
  4324. cancellation: CancellationToken,
  4325. ): Promise<void> {
  4326. + console.log('resolveWebviewView', webviewHandle, viewType, title, state);
  4327. + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'resolveWebviewView start: ' + viewType);
  4328. const entry = this._viewProviders.get(viewType);
  4329. if (!entry) {
  4330. throw new Error(`No view provider found for '${viewType}'`);
  4331. diff --git a/src/vs/workbench/api/common/extHostWorkspace.ts b/src/vs/workbench/api/common/extHostWorkspace.ts
  4332. index 12af1c17f95..2e2b55b1fa4 100644
  4333. --- a/src/vs/workbench/api/common/extHostWorkspace.ts
  4334. +++ b/src/vs/workbench/api/common/extHostWorkspace.ts
  4335. @@ -227,6 +227,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac
  4336. }
  4337. $initializeWorkspace(data: IWorkspaceData | null, trusted: boolean): void {
  4338. + console.log('initializeWorkspace', data, trusted);
  4339. this._trusted = trusted;
  4340. this.$acceptWorkspaceData(data);
  4341. this._barrier.open();
  4342. diff --git a/src/vs/workbench/api/common/extensionHostMain.ts b/src/vs/workbench/api/common/extensionHostMain.ts
  4343. index 11980f9aafe..24d9a7aeca4 100644
  4344. --- a/src/vs/workbench/api/common/extensionHostMain.ts
  4345. +++ b/src/vs/workbench/api/common/extensionHostMain.ts
  4346. @@ -3,220 +3,236 @@
  4347. * Licensed under the MIT License. See License.txt in the project root for license information.
  4348. *--------------------------------------------------------------------------------------------*/
  4349. -import * as errors from '../../../base/common/errors.js';
  4350. -import * as performance from '../../../base/common/performance.js';
  4351. -import { URI } from '../../../base/common/uri.js';
  4352. -import { IURITransformer } from '../../../base/common/uriIpc.js';
  4353. -import { IMessagePassingProtocol } from '../../../base/parts/ipc/common/ipc.js';
  4354. -import { MainContext, MainThreadConsoleShape } from './extHost.protocol.js';
  4355. -import { IExtensionHostInitData } from '../../services/extensions/common/extensionHostProtocol.js';
  4356. -import { RPCProtocol } from '../../services/extensions/common/rpcProtocol.js';
  4357. -import { ExtensionError, ExtensionIdentifier, IExtensionDescription } from '../../../platform/extensions/common/extensions.js';
  4358. -import { ILogService } from '../../../platform/log/common/log.js';
  4359. -import { getSingletonServiceDescriptors } from '../../../platform/instantiation/common/extensions.js';
  4360. -import { ServiceCollection } from '../../../platform/instantiation/common/serviceCollection.js';
  4361. -import { IExtHostInitDataService } from './extHostInitDataService.js';
  4362. -import { InstantiationService } from '../../../platform/instantiation/common/instantiationService.js';
  4363. -import { IInstantiationService, ServicesAccessor } from '../../../platform/instantiation/common/instantiation.js';
  4364. -import { IExtHostRpcService, ExtHostRpcService } from './extHostRpcService.js';
  4365. -import { IURITransformerService, URITransformerService } from './extHostUriTransformerService.js';
  4366. -import { IExtHostExtensionService, IHostUtils } from './extHostExtensionService.js';
  4367. -import { IExtHostTelemetry } from './extHostTelemetry.js';
  4368. -import { Mutable } from '../../../base/common/types.js';
  4369. +import * as errors from "../../../base/common/errors.js"
  4370. +import * as performance from "../../../base/common/performance.js"
  4371. +import { URI } from "../../../base/common/uri.js"
  4372. +import { IURITransformer } from "../../../base/common/uriIpc.js"
  4373. +import { IMessagePassingProtocol } from "../../../base/parts/ipc/common/ipc.js"
  4374. +import { MainContext, MainThreadConsoleShape } from "./extHost.protocol.js"
  4375. +import { IExtensionHostInitData } from "../../services/extensions/common/extensionHostProtocol.js"
  4376. +import { RPCProtocol } from "../../services/extensions/common/rpcProtocol.js"
  4377. +import {
  4378. + ExtensionError,
  4379. + ExtensionIdentifier,
  4380. + IExtensionDescription,
  4381. +} from "../../../platform/extensions/common/extensions.js"
  4382. +import { ILogService } from "../../../platform/log/common/log.js"
  4383. +import { getSingletonServiceDescriptors } from "../../../platform/instantiation/common/extensions.js"
  4384. +import { ServiceCollection } from "../../../platform/instantiation/common/serviceCollection.js"
  4385. +import { IExtHostInitDataService } from "./extHostInitDataService.js"
  4386. +import { InstantiationService } from "../../../platform/instantiation/common/instantiationService.js"
  4387. +import { IInstantiationService, ServicesAccessor } from "../../../platform/instantiation/common/instantiation.js"
  4388. +import { IExtHostRpcService, ExtHostRpcService } from "./extHostRpcService.js"
  4389. +import { IURITransformerService, URITransformerService } from "./extHostUriTransformerService.js"
  4390. +import { IExtHostExtensionService, IHostUtils } from "./extHostExtensionService.js"
  4391. +import { IExtHostTelemetry } from "./extHostTelemetry.js"
  4392. +import { Mutable } from "../../../base/common/types.js"
  4393. +import { FileRPCProtocolLogger } from "../../services/extensions/common/fileRPCProtocolLogger.js"
  4394. export interface IExitFn {
  4395. - (code?: number): any;
  4396. + (code?: number): any
  4397. }
  4398. export interface IConsolePatchFn {
  4399. - (mainThreadConsole: MainThreadConsoleShape): any;
  4400. + (mainThreadConsole: MainThreadConsoleShape): any
  4401. }
  4402. export abstract class ErrorHandler {
  4403. -
  4404. static async installEarlyHandler(accessor: ServicesAccessor): Promise<void> {
  4405. -
  4406. // increase number of stack frames (from 10, https://github.com/v8/v8/wiki/Stack-Trace-API)
  4407. - Error.stackTraceLimit = 100;
  4408. + Error.stackTraceLimit = 100
  4409. // does NOT dependent of extension information, can be installed immediately, and simply forwards
  4410. // to the log service and main thread errors
  4411. - const logService = accessor.get(ILogService);
  4412. - const rpcService = accessor.get(IExtHostRpcService);
  4413. - const mainThreadErrors = rpcService.getProxy(MainContext.MainThreadErrors);
  4414. -
  4415. - errors.setUnexpectedErrorHandler(err => {
  4416. - logService.error(err);
  4417. - const data = errors.transformErrorForSerialization(err);
  4418. - mainThreadErrors.$onUnexpectedError(data);
  4419. - });
  4420. + const logService = accessor.get(ILogService)
  4421. + const rpcService = accessor.get(IExtHostRpcService)
  4422. + const mainThreadErrors = rpcService.getProxy(MainContext.MainThreadErrors)
  4423. +
  4424. + errors.setUnexpectedErrorHandler((err) => {
  4425. + logService.error(err)
  4426. + const data = errors.transformErrorForSerialization(err)
  4427. + mainThreadErrors.$onUnexpectedError(data)
  4428. + })
  4429. }
  4430. static async installFullHandler(accessor: ServicesAccessor): Promise<void> {
  4431. // uses extension knowledges to correlate errors with extensions
  4432. - const logService = accessor.get(ILogService);
  4433. - const rpcService = accessor.get(IExtHostRpcService);
  4434. - const extensionService = accessor.get(IExtHostExtensionService);
  4435. - const extensionTelemetry = accessor.get(IExtHostTelemetry);
  4436. + const logService = accessor.get(ILogService)
  4437. + const rpcService = accessor.get(IExtHostRpcService)
  4438. + const extensionService = accessor.get(IExtHostExtensionService)
  4439. + const extensionTelemetry = accessor.get(IExtHostTelemetry)
  4440. - const mainThreadExtensions = rpcService.getProxy(MainContext.MainThreadExtensionService);
  4441. - const mainThreadErrors = rpcService.getProxy(MainContext.MainThreadErrors);
  4442. + const mainThreadExtensions = rpcService.getProxy(MainContext.MainThreadExtensionService)
  4443. + const mainThreadErrors = rpcService.getProxy(MainContext.MainThreadErrors)
  4444. - const map = await extensionService.getExtensionPathIndex();
  4445. - const extensionErrors = new WeakMap<Error, { extensionIdentifier: ExtensionIdentifier | undefined; stack: string }>();
  4446. + const map = await extensionService.getExtensionPathIndex()
  4447. + const extensionErrors = new WeakMap<
  4448. + Error,
  4449. + { extensionIdentifier: ExtensionIdentifier | undefined; stack: string }
  4450. + >()
  4451. // PART 1
  4452. // set the prepareStackTrace-handle and use it as a side-effect to associate errors
  4453. // with extensions - this works by looking up callsites in the extension path index
  4454. function prepareStackTraceAndFindExtension(error: Error, stackTrace: errors.V8CallSite[]) {
  4455. if (extensionErrors.has(error)) {
  4456. - return extensionErrors.get(error)!.stack;
  4457. + return extensionErrors.get(error)!.stack
  4458. }
  4459. - let stackTraceMessage = '';
  4460. - let extension: IExtensionDescription | undefined;
  4461. - let fileName: string | null;
  4462. + let stackTraceMessage = ""
  4463. + let extension: IExtensionDescription | undefined
  4464. + let fileName: string | null
  4465. for (const call of stackTrace) {
  4466. - stackTraceMessage += `\n\tat ${call.toString()}`;
  4467. - fileName = call.getFileName();
  4468. + stackTraceMessage += `\n\tat ${call.toString()}`
  4469. + fileName = call.getFileName()
  4470. if (!extension && fileName) {
  4471. - extension = map.findSubstr(URI.file(fileName));
  4472. + extension = map.findSubstr(URI.file(fileName))
  4473. }
  4474. }
  4475. - const result = `${error.name || 'Error'}: ${error.message || ''}${stackTraceMessage}`;
  4476. - extensionErrors.set(error, { extensionIdentifier: extension?.identifier, stack: result });
  4477. - return result;
  4478. + const result = `${error.name || "Error"}: ${error.message || ""}${stackTraceMessage}`
  4479. + extensionErrors.set(error, { extensionIdentifier: extension?.identifier, stack: result })
  4480. + return result
  4481. }
  4482. - const _wasWrapped = Symbol('prepareStackTrace wrapped');
  4483. - let _prepareStackTrace = prepareStackTraceAndFindExtension;
  4484. + const _wasWrapped = Symbol("prepareStackTrace wrapped")
  4485. + let _prepareStackTrace = prepareStackTraceAndFindExtension
  4486. - Object.defineProperty(Error, 'prepareStackTrace', {
  4487. + Object.defineProperty(Error, "prepareStackTrace", {
  4488. configurable: false,
  4489. get() {
  4490. - return _prepareStackTrace;
  4491. + return _prepareStackTrace
  4492. },
  4493. set(v) {
  4494. if (v === prepareStackTraceAndFindExtension || !v || v[_wasWrapped]) {
  4495. - _prepareStackTrace = v || prepareStackTraceAndFindExtension;
  4496. - return;
  4497. + _prepareStackTrace = v || prepareStackTraceAndFindExtension
  4498. + return
  4499. }
  4500. _prepareStackTrace = function (error, stackTrace) {
  4501. - prepareStackTraceAndFindExtension(error, stackTrace);
  4502. - return v.call(Error, error, stackTrace);
  4503. - };
  4504. + prepareStackTraceAndFindExtension(error, stackTrace)
  4505. + return v.call(Error, error, stackTrace)
  4506. + }
  4507. - Object.assign(_prepareStackTrace, { [_wasWrapped]: true });
  4508. + Object.assign(_prepareStackTrace, { [_wasWrapped]: true })
  4509. },
  4510. - });
  4511. + })
  4512. // PART 2
  4513. // set the unexpectedErrorHandler and check for extensions that have been identified as
  4514. // having caused the error. Note that the runtime order is actually reversed, the code
  4515. // below accesses the stack-property which triggers the code above
  4516. - errors.setUnexpectedErrorHandler(err => {
  4517. - logService.error(err);
  4518. + errors.setUnexpectedErrorHandler((err) => {
  4519. + logService.error(err)
  4520. - const errorData = errors.transformErrorForSerialization(err);
  4521. + const errorData = errors.transformErrorForSerialization(err)
  4522. - let extension: ExtensionIdentifier | undefined;
  4523. + let extension: ExtensionIdentifier | undefined
  4524. if (err instanceof ExtensionError) {
  4525. - extension = err.extension;
  4526. + extension = err.extension
  4527. } else {
  4528. - const stackData = extensionErrors.get(err);
  4529. - extension = stackData?.extensionIdentifier;
  4530. + const stackData = extensionErrors.get(err)
  4531. + extension = stackData?.extensionIdentifier
  4532. }
  4533. if (extension) {
  4534. - mainThreadExtensions.$onExtensionRuntimeError(extension, errorData);
  4535. - const reported = extensionTelemetry.onExtensionError(extension, err);
  4536. - logService.trace('forwarded error to extension?', reported, extension);
  4537. + mainThreadExtensions.$onExtensionRuntimeError(extension, errorData)
  4538. + const reported = extensionTelemetry.onExtensionError(extension, err)
  4539. + logService.trace("forwarded error to extension?", reported, extension)
  4540. }
  4541. - });
  4542. + })
  4543. - errors.errorHandler.addListener(err => {
  4544. - mainThreadErrors.$onUnexpectedError(err);
  4545. - });
  4546. + errors.errorHandler.addListener((err) => {
  4547. + const data = errors.transformErrorForSerialization(err)
  4548. + mainThreadErrors.$onUnexpectedError(data)
  4549. + })
  4550. }
  4551. }
  4552. export class ExtensionHostMain {
  4553. -
  4554. - private readonly _hostUtils: IHostUtils;
  4555. - private readonly _rpcProtocol: RPCProtocol;
  4556. - private readonly _extensionService: IExtHostExtensionService;
  4557. - private readonly _logService: ILogService;
  4558. + private readonly _hostUtils: IHostUtils
  4559. + private readonly _rpcProtocol: RPCProtocol
  4560. + private readonly _extensionService: IExtHostExtensionService
  4561. + private readonly _logService: ILogService
  4562. constructor(
  4563. protocol: IMessagePassingProtocol,
  4564. initData: IExtensionHostInitData,
  4565. hostUtils: IHostUtils,
  4566. uriTransformer: IURITransformer | null,
  4567. - messagePorts?: ReadonlyMap<string, MessagePort>
  4568. + messagePorts?: ReadonlyMap<string, MessagePort>,
  4569. ) {
  4570. - this._hostUtils = hostUtils;
  4571. - this._rpcProtocol = new RPCProtocol(protocol, null, uriTransformer);
  4572. + this._hostUtils = hostUtils
  4573. + this._rpcProtocol = new RPCProtocol(protocol, new FileRPCProtocolLogger("extension_protocol"), uriTransformer)
  4574. // ensure URIs are transformed and revived
  4575. - initData = ExtensionHostMain._transform(initData, this._rpcProtocol);
  4576. + initData = ExtensionHostMain._transform(initData, this._rpcProtocol)
  4577. // bootstrap services
  4578. - const services = new ServiceCollection(...getSingletonServiceDescriptors());
  4579. - services.set(IExtHostInitDataService, { _serviceBrand: undefined, ...initData, messagePorts });
  4580. - services.set(IExtHostRpcService, new ExtHostRpcService(this._rpcProtocol));
  4581. - services.set(IURITransformerService, new URITransformerService(uriTransformer));
  4582. - services.set(IHostUtils, hostUtils);
  4583. + const services = new ServiceCollection(...getSingletonServiceDescriptors())
  4584. + services.set(IExtHostInitDataService, { _serviceBrand: undefined, ...initData, messagePorts })
  4585. + services.set(IExtHostRpcService, new ExtHostRpcService(this._rpcProtocol))
  4586. + services.set(IURITransformerService, new URITransformerService(uriTransformer))
  4587. + services.set(IHostUtils, hostUtils)
  4588. - const instaService: IInstantiationService = new InstantiationService(services, true);
  4589. + const instaService: IInstantiationService = new InstantiationService(services, true)
  4590. - instaService.invokeFunction(ErrorHandler.installEarlyHandler);
  4591. + instaService.invokeFunction(ErrorHandler.installEarlyHandler)
  4592. // ugly self - inject
  4593. - this._logService = instaService.invokeFunction(accessor => accessor.get(ILogService));
  4594. + this._logService = instaService.invokeFunction((accessor) => accessor.get(ILogService))
  4595. - performance.mark(`code/extHost/didCreateServices`);
  4596. + performance.mark(`code/extHost/didCreateServices`)
  4597. if (this._hostUtils.pid) {
  4598. - this._logService.info(`Extension host with pid ${this._hostUtils.pid} started`);
  4599. + this._logService.info(`Extension host with pid ${this._hostUtils.pid} started`)
  4600. } else {
  4601. - this._logService.info(`Extension host started`);
  4602. + this._logService.info(`Extension host started`)
  4603. }
  4604. - this._logService.trace('initData', initData);
  4605. + this._logService.trace("initData", initData)
  4606. // ugly self - inject
  4607. // must call initialize *after* creating the extension service
  4608. // because `initialize` itself creates instances that depend on it
  4609. - this._extensionService = instaService.invokeFunction(accessor => accessor.get(IExtHostExtensionService));
  4610. - this._extensionService.initialize();
  4611. + this._extensionService = instaService.invokeFunction((accessor) => accessor.get(IExtHostExtensionService))
  4612. + this._extensionService.initialize()
  4613. // install error handler that is extension-aware
  4614. - instaService.invokeFunction(ErrorHandler.installFullHandler);
  4615. + instaService.invokeFunction(ErrorHandler.installFullHandler)
  4616. }
  4617. async asBrowserUri(uri: URI): Promise<URI> {
  4618. - const mainThreadExtensionsProxy = this._rpcProtocol.getProxy(MainContext.MainThreadExtensionService);
  4619. - return URI.revive(await mainThreadExtensionsProxy.$asBrowserUri(uri));
  4620. + const mainThreadExtensionsProxy = this._rpcProtocol.getProxy(MainContext.MainThreadExtensionService)
  4621. + return URI.revive(await mainThreadExtensionsProxy.$asBrowserUri(uri))
  4622. }
  4623. terminate(reason: string): void {
  4624. - this._extensionService.terminate(reason);
  4625. + this._extensionService.terminate(reason)
  4626. }
  4627. private static _transform(initData: IExtensionHostInitData, rpcProtocol: RPCProtocol): IExtensionHostInitData {
  4628. initData.extensions.allExtensions.forEach((ext) => {
  4629. - (<Mutable<IExtensionDescription>>ext).extensionLocation = URI.revive(rpcProtocol.transformIncomingURIs(ext.extensionLocation));
  4630. - });
  4631. - initData.environment.appRoot = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.appRoot));
  4632. - const extDevLocs = initData.environment.extensionDevelopmentLocationURI;
  4633. + ;(<Mutable<IExtensionDescription>>ext).extensionLocation = URI.revive(
  4634. + rpcProtocol.transformIncomingURIs(ext.extensionLocation),
  4635. + )
  4636. + })
  4637. + initData.environment.appRoot = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.appRoot))
  4638. + const extDevLocs = initData.environment.extensionDevelopmentLocationURI
  4639. if (extDevLocs) {
  4640. - initData.environment.extensionDevelopmentLocationURI = extDevLocs.map(url => URI.revive(rpcProtocol.transformIncomingURIs(url)));
  4641. + initData.environment.extensionDevelopmentLocationURI = extDevLocs.map((url) =>
  4642. + URI.revive(rpcProtocol.transformIncomingURIs(url)),
  4643. + )
  4644. }
  4645. - initData.environment.extensionTestsLocationURI = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.extensionTestsLocationURI));
  4646. - initData.environment.globalStorageHome = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.globalStorageHome));
  4647. - initData.environment.workspaceStorageHome = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.workspaceStorageHome));
  4648. - initData.nlsBaseUrl = URI.revive(rpcProtocol.transformIncomingURIs(initData.nlsBaseUrl));
  4649. - initData.logsLocation = URI.revive(rpcProtocol.transformIncomingURIs(initData.logsLocation));
  4650. - initData.workspace = rpcProtocol.transformIncomingURIs(initData.workspace);
  4651. - return initData;
  4652. + initData.environment.extensionTestsLocationURI = URI.revive(
  4653. + rpcProtocol.transformIncomingURIs(initData.environment.extensionTestsLocationURI),
  4654. + )
  4655. + initData.environment.globalStorageHome = URI.revive(
  4656. + rpcProtocol.transformIncomingURIs(initData.environment.globalStorageHome),
  4657. + )
  4658. + initData.environment.workspaceStorageHome = URI.revive(
  4659. + rpcProtocol.transformIncomingURIs(initData.environment.workspaceStorageHome),
  4660. + )
  4661. + initData.nlsBaseUrl = URI.revive(rpcProtocol.transformIncomingURIs(initData.nlsBaseUrl))
  4662. + initData.logsLocation = URI.revive(rpcProtocol.transformIncomingURIs(initData.logsLocation))
  4663. + initData.workspace = rpcProtocol.transformIncomingURIs(initData.workspace)
  4664. + return initData
  4665. }
  4666. }
  4667. diff --git a/src/vs/workbench/api/node/extHostConsoleForwarder.ts b/src/vs/workbench/api/node/extHostConsoleForwarder.ts
  4668. index aa2dbca286c..d9eb33a7043 100644
  4669. --- a/src/vs/workbench/api/node/extHostConsoleForwarder.ts
  4670. +++ b/src/vs/workbench/api/node/extHostConsoleForwarder.ts
  4671. @@ -47,7 +47,7 @@ export class ExtHostConsoleForwarder extends AbstractExtHostConsoleForwarder {
  4672. Object.defineProperty(stream, 'write', {
  4673. set: () => { },
  4674. - get: () => (chunk: Uint8Array | string, encoding?: BufferEncoding, callback?: (err?: Error) => void) => {
  4675. + get: () => (chunk: Uint8Array | string, encoding?: BufferEncoding, callback?: (err?: Error | null) => void) => {
  4676. if (!this._isMakingConsoleCall) {
  4677. buf += (chunk as any).toString(encoding);
  4678. const eol = buf.length > MAX_STREAM_BUFFER_LENGTH ? buf.length : buf.lastIndexOf('\n');
  4679. diff --git a/src/vs/workbench/api/node/extensionHostProcess.ts b/src/vs/workbench/api/node/extensionHostProcess.ts
  4680. index 704a0dbb5bd..aa61052558e 100644
  4681. --- a/src/vs/workbench/api/node/extensionHostProcess.ts
  4682. +++ b/src/vs/workbench/api/node/extensionHostProcess.ts
  4683. @@ -29,6 +29,8 @@ import { IDisposable } from '../../../base/common/lifecycle.js';
  4684. import '../common/extHost.common.services.js';
  4685. import './extHost.node.services.js';
  4686. import { createRequire } from 'node:module';
  4687. +import { fileLoggerGlobal } from '../../../../../../src/extension.js';
  4688. +import { RequestInitiator } from '../../services/extensions/common/rpcProtocol.js';
  4689. const require = createRequire(import.meta.url);
  4690. interface ParsedExtHostArgs {
  4691. @@ -186,6 +188,7 @@ function _createExtHostProtocol(): Promise<IMessagePassingProtocol> {
  4692. socket = new WebSocketNodeSocket(new NodeSocket(handle, 'extHost-socket'), msg.permessageDeflate, inflateBytes, false);
  4693. }
  4694. if (protocol) {
  4695. + fileLoggerGlobal.logOutgoing(0, 0, RequestInitiator.LocalSide, 'Reconnection case');
  4696. // reconnection case
  4697. disconnectRunner1.cancel();
  4698. disconnectRunner2.cancel();
  4699. @@ -193,6 +196,7 @@ function _createExtHostProtocol(): Promise<IMessagePassingProtocol> {
  4700. protocol.endAcceptReconnection();
  4701. protocol.sendResume();
  4702. } else {
  4703. + fileLoggerGlobal.logOutgoing(0, 0, RequestInitiator.LocalSide, 'New connection case');
  4704. clearTimeout(timer);
  4705. protocol = new PersistentProtocol({ socket, initialChunk: initialDataChunk });
  4706. protocol.sendResume();
  4707. @@ -207,6 +211,7 @@ function _createExtHostProtocol(): Promise<IMessagePassingProtocol> {
  4708. }
  4709. }
  4710. if (msg && msg.type === 'VSCODE_EXTHOST_IPC_REDUCE_GRACE_TIME') {
  4711. + fileLoggerGlobal.logOutgoing(0, 0, RequestInitiator.LocalSide, 'Reduce grace time case');
  4712. if (disconnectRunner2.isScheduled()) {
  4713. // we are disconnected and already running the short reconnection timer
  4714. return;
  4715. @@ -338,12 +343,14 @@ function connectToRenderer(protocol: IMessagePassingProtocol): Promise<IRenderer
  4716. }
  4717. // Tell the outside that we are initialized
  4718. + console.log('send initialized message');
  4719. protocol.send(createMessageOfType(MessageType.Initialized));
  4720. c({ protocol, initData });
  4721. });
  4722. // Tell the outside that we are ready to receive messages
  4723. + console.log('send ready message');
  4724. protocol.send(createMessageOfType(MessageType.Ready));
  4725. });
  4726. }
  4727. @@ -426,4 +433,8 @@ async function startExtensionHostProcess(): Promise<void> {
  4728. onTerminate = (reason: string) => extensionHostMain.terminate(reason);
  4729. }
  4730. -startExtensionHostProcess().catch((err) => console.log(err));
  4731. +function start() {
  4732. + startExtensionHostProcess().catch((err) => console.log(err));
  4733. +}
  4734. +
  4735. +export default start;
  4736. \ No newline at end of file
  4737. diff --git a/src/vs/workbench/contrib/webview/common/webview.ts b/src/vs/workbench/contrib/webview/common/webview.ts
  4738. index 95c65048fcd..31aaea4a722 100644
  4739. --- a/src/vs/workbench/contrib/webview/common/webview.ts
  4740. +++ b/src/vs/workbench/contrib/webview/common/webview.ts
  4741. @@ -22,7 +22,7 @@ export const webviewResourceBaseHost = 'vscode-cdn.net';
  4742. export const webviewRootResourceAuthority = `vscode-resource.${webviewResourceBaseHost}`;
  4743. -export const webviewGenericCspSource = `'self' https://*.${webviewResourceBaseHost}`;
  4744. +export const webviewGenericCspSource = `'self' https://*.${webviewResourceBaseHost} vscode-file://*`;
  4745. /**
  4746. * Construct a uri that can load resources inside a webview
  4747. @@ -42,6 +42,15 @@ export function asWebviewUri(resource: URI, remoteInfo?: WebviewRemoteInfo): URI
  4748. return resource;
  4749. }
  4750. + if (resource.scheme === Schemas.file) {
  4751. + return URI.from({
  4752. + scheme: "vscode-file",
  4753. + path: resource.path,
  4754. + fragment: resource.fragment,
  4755. + query: resource.query,
  4756. + });
  4757. + }
  4758. +
  4759. if (remoteInfo && remoteInfo.authority && remoteInfo.isRemote && resource.scheme === Schemas.file) {
  4760. resource = URI.from({
  4761. scheme: Schemas.vscodeRemote,
  4762. diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts
  4763. index 382683f3cf7..4478914fdc6 100644
  4764. --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts
  4765. +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts
  4766. @@ -813,6 +813,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx
  4767. const disposableStore = new DisposableStore();
  4768. disposableStore.add(processManager.onDidExit(([code, signal]) => this._onExtensionHostCrashOrExit(processManager, code, signal)));
  4769. disposableStore.add(processManager.onDidChangeResponsiveState((responsiveState) => {
  4770. + console.log(`Extension host (${processManager.friendyName}) is ${responsiveState === ResponsiveState.Responsive ? 'responsive' : 'unresponsive'}.`);
  4771. this._logService.info(`Extension host (${processManager.friendyName}) is ${responsiveState === ResponsiveState.Responsive ? 'responsive' : 'unresponsive'}.`);
  4772. this._onDidChangeResponsiveChange.fire({
  4773. extensionHostKind: processManager.kind,
  4774. diff --git a/src/vs/workbench/services/extensions/common/fileRPCProtocolLogger.ts b/src/vs/workbench/services/extensions/common/fileRPCProtocolLogger.ts
  4775. new file mode 100644
  4776. index 00000000000..1b4fc52e001
  4777. --- /dev/null
  4778. +++ b/src/vs/workbench/services/extensions/common/fileRPCProtocolLogger.ts
  4779. @@ -0,0 +1,246 @@
  4780. +/*---------------------------------------------------------------------------------------------
  4781. + * Copyright (c) Microsoft Corporation. All rights reserved.
  4782. + * Licensed under the MIT License. See License.txt in the project root for license information.
  4783. + *--------------------------------------------------------------------------------------------*/
  4784. +
  4785. +import * as fs from "fs"
  4786. +import * as path from "path"
  4787. +import * as os from "os"
  4788. +import { IRPCProtocolLogger, RequestInitiator } from "./rpcProtocol.js"
  4789. +
  4790. +/**
  4791. + * 文件RPC协议日志记录器,将RPC通信日志保存到文件中
  4792. + */
  4793. +export class FileRPCProtocolLogger implements IRPCProtocolLogger {
  4794. + private _totalIncoming = 0
  4795. + private _totalOutgoing = 0
  4796. + private _logDir: string | undefined
  4797. + private _logFile: string | undefined
  4798. + private _writeStream: fs.WriteStream | null = null
  4799. + private _logQueue: string[] = []
  4800. + private _isInitialized = false
  4801. + private _isDisposed = false
  4802. + private _processInterval: NodeJS.Timeout | null = null
  4803. + private _isEnabled = false
  4804. +
  4805. + constructor(suffix?: string) {
  4806. + if(!this._isEnabled) {
  4807. + return
  4808. + }
  4809. + this._logDir = path.join(os.homedir(), ".ext_host", "log")
  4810. + this._ensureLogDirectoryExists()
  4811. +
  4812. + // 创建日志文件名,使用时间戳确保唯一性
  4813. + const timestamp = new Date().toISOString().replace(/[:.]/g, "-").replace("T", "_").slice(0, 19)
  4814. +
  4815. + // 如果提供了后缀,在文件名中添加
  4816. + const suffixPart = suffix ? `_${suffix}` : '';
  4817. + this._logFile = path.join(this._logDir, `rpc${suffixPart}_${timestamp}.log`)
  4818. +
  4819. + try {
  4820. + // 创建日志文件写入流
  4821. + this._writeStream = fs.createWriteStream(this._logFile, { flags: "a" })
  4822. +
  4823. + // 生成精确到毫秒的时间戳
  4824. + const now = new Date()
  4825. + const startTime = this._formatTimestampWithMilliseconds(now)
  4826. +
  4827. + // 写入日志头
  4828. + const header = [
  4829. + "-------------------------------------------------------------",
  4830. + "Extension Host RPC Protocol Logger",
  4831. + `Started at: ${startTime}`,
  4832. + `Log file: ${this._logFile}`,
  4833. + "-------------------------------------------------------------",
  4834. + ""
  4835. + ].join("\n")
  4836. +
  4837. + this._logQueue.push(header)
  4838. +
  4839. + // 启动日志处理定时器
  4840. + this._startProcessingQueue()
  4841. +
  4842. + this._isInitialized = true
  4843. + console.log(`FileRPCProtocolLogger initialized, log file: ${this._logFile}`)
  4844. + } catch (e) {
  4845. + console.error("Failed to initialize FileRPCProtocolLogger", e)
  4846. + }
  4847. + }
  4848. +
  4849. + /**
  4850. + * 确保日志目录存在
  4851. + */
  4852. + private _ensureLogDirectoryExists(): void {
  4853. + if(!this._logDir) {
  4854. + return
  4855. + }
  4856. + try {
  4857. + if (!fs.existsSync(this._logDir)) {
  4858. + fs.mkdirSync(this._logDir, { recursive: true })
  4859. + }
  4860. + } catch (e) {
  4861. + console.error("Failed to create log directory", e)
  4862. + }
  4863. + }
  4864. +
  4865. + /**
  4866. + * 启动队列处理定时器
  4867. + */
  4868. + private _startProcessingQueue(): void {
  4869. + this._processInterval = setInterval(() => {
  4870. + this._processQueue()
  4871. + }, 100) // 100毫秒处理一次队列
  4872. + }
  4873. +
  4874. + /**
  4875. + * 处理日志队列
  4876. + */
  4877. + private _processQueue(): void {
  4878. + if (this._isDisposed || !this._writeStream || this._logQueue.length === 0) {
  4879. + return
  4880. + }
  4881. +
  4882. + try {
  4883. + // 批量写入日志条目
  4884. + const entries = this._logQueue.splice(0, Math.min(50, this._logQueue.length))
  4885. + for (const entry of entries) {
  4886. + this._writeStream.write(entry + "\n")
  4887. + }
  4888. + } catch (e) {
  4889. + console.error("Failed to write log entries", e)
  4890. + }
  4891. + }
  4892. +
  4893. + /**
  4894. + * 记录传入消息日志
  4895. + */
  4896. + logIncoming(msgLength: number, req: number, initiator: RequestInitiator, str: string, data?: any): void {
  4897. + if (!this._isInitialized) {
  4898. + return
  4899. + }
  4900. +
  4901. + this._totalIncoming += msgLength
  4902. + this._logMessage("IDEA → Ext", this._totalIncoming, msgLength, req, initiator, str, data)
  4903. + }
  4904. +
  4905. + /**
  4906. + * 记录传出消息日志
  4907. + */
  4908. + logOutgoing(msgLength: number, req: number, initiator: RequestInitiator, str: string, data?: any): void {
  4909. + if (!this._isInitialized) {
  4910. + return
  4911. + }
  4912. +
  4913. + this._totalOutgoing += msgLength
  4914. + this._logMessage("Ext → IDEA", this._totalOutgoing, msgLength, req, initiator, str, data)
  4915. + }
  4916. +
  4917. + /**
  4918. + * 记录消息
  4919. + */
  4920. + private _logMessage(
  4921. + direction: string,
  4922. + totalLength: number,
  4923. + msgLength: number,
  4924. + req: number,
  4925. + initiator: RequestInitiator,
  4926. + str: string,
  4927. + data: any
  4928. + ): void {
  4929. + try {
  4930. + const now = new Date()
  4931. + const timestamp = this._formatTimestampWithMilliseconds(now)
  4932. +
  4933. + const initiatorStr = initiator === RequestInitiator.LocalSide ? "Local" : "Other"
  4934. +
  4935. + let logEntry = `[${timestamp}] `
  4936. + logEntry += `[${direction}] `
  4937. + logEntry += `[Total: ${String(totalLength).padStart(7)}] `
  4938. + logEntry += `[Len: ${String(msgLength).padStart(5)}] `
  4939. + logEntry += `[${String(req).padStart(5)}] `
  4940. + logEntry += `[${initiatorStr}] `
  4941. + logEntry += str
  4942. +
  4943. + if (data !== undefined) {
  4944. + const dataStr = /\($/.test(str) ? `${this._stringify(data)})` : this._stringify(data)
  4945. + logEntry += ` ${dataStr}`
  4946. + }
  4947. +
  4948. + this._logQueue.push(logEntry)
  4949. + } catch (e) {
  4950. + console.error("Failed to format log message", e)
  4951. + }
  4952. + }
  4953. +
  4954. + /**
  4955. + * 安全地将数据转换为字符串
  4956. + */
  4957. + private _stringify(data: any): string {
  4958. + try {
  4959. + return JSON.stringify(data, null, 0)
  4960. + } catch (e) {
  4961. + return String(data)
  4962. + }
  4963. + }
  4964. +
  4965. + /**
  4966. + * 释放资源
  4967. + */
  4968. + dispose(): void {
  4969. + if (this._isDisposed) {
  4970. + return
  4971. + }
  4972. +
  4973. + this._isDisposed = true
  4974. +
  4975. + try {
  4976. + // 清除定时器
  4977. + if (this._processInterval) {
  4978. + clearInterval(this._processInterval)
  4979. + this._processInterval = null
  4980. + }
  4981. +
  4982. + // 处理剩余的队列条目
  4983. + this._processQueue()
  4984. +
  4985. + // 生成精确到毫秒的时间戳
  4986. + const now = new Date()
  4987. + const endTime = this._formatTimestampWithMilliseconds(now)
  4988. +
  4989. + // 写入日志尾
  4990. + const footer = [
  4991. + "-------------------------------------------------------------",
  4992. + "Extension Host RPC Protocol Logger",
  4993. + `Ended at: ${endTime}`,
  4994. + `Total incoming: ${this._totalIncoming} bytes`,
  4995. + `Total outgoing: ${this._totalOutgoing} bytes`,
  4996. + "-------------------------------------------------------------"
  4997. + ].join("\n")
  4998. +
  4999. + // 直接写入,不经过队列
  5000. + if (this._writeStream) {
  5001. + this._writeStream.write(footer + "\n")
  5002. + this._writeStream.end()
  5003. + this._writeStream = null
  5004. + }
  5005. +
  5006. + console.log("FileRPCProtocolLogger disposed")
  5007. + } catch (e) {
  5008. + console.error("Failed to dispose FileRPCProtocolLogger", e)
  5009. + }
  5010. + }
  5011. +
  5012. + /**
  5013. + * 格式化时间戳为毫秒级别
  5014. + */
  5015. + private _formatTimestampWithMilliseconds(date: Date): string {
  5016. + const year = date.getFullYear()
  5017. + const month = String(date.getMonth() + 1).padStart(2, '0')
  5018. + const day = String(date.getDate()).padStart(2, '0')
  5019. + const hours = String(date.getHours()).padStart(2, '0')
  5020. + const minutes = String(date.getMinutes()).padStart(2, '0')
  5021. + const seconds = String(date.getSeconds()).padStart(2, '0')
  5022. + const milliseconds = String(date.getMilliseconds()).padStart(3, '0')
  5023. + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${milliseconds}`
  5024. + }
  5025. +}
  5026. \ No newline at end of file
  5027. diff --git a/src/vs/workbench/services/extensions/common/rpcProtocol.ts b/src/vs/workbench/services/extensions/common/rpcProtocol.ts
  5028. index 6467e585843..eeb99f77f4a 100644
  5029. --- a/src/vs/workbench/services/extensions/common/rpcProtocol.ts
  5030. +++ b/src/vs/workbench/services/extensions/common/rpcProtocol.ts
  5031. @@ -288,6 +288,7 @@ export class RPCProtocol extends Disposable implements IRPCProtocol {
  5032. const buff = MessageBuffer.read(rawmsg, 0);
  5033. const messageType = <MessageType>buff.readUInt8();
  5034. const req = buff.readUInt32();
  5035. + this._logger?.logIncoming(msgLength, req, RequestInitiator.OtherSide, `receiveMessage: ${messageType}, req: ${req}, msgType: ${messageType}`);
  5036. switch (messageType) {
  5037. case MessageType.RequestJSONArgs:
  5038. @@ -309,7 +310,7 @@ export class RPCProtocol extends Disposable implements IRPCProtocol {
  5039. break;
  5040. }
  5041. case MessageType.Acknowledged: {
  5042. - this._logger?.logIncoming(msgLength, req, RequestInitiator.LocalSide, `ack`);
  5043. + // this._logger?.logIncoming(msgLength, req, RequestInitiator.LocalSide, `ack`);
  5044. this._onDidReceiveAcknowledge(req);
  5045. break;
  5046. }
  5047. @@ -442,6 +443,7 @@ export class RPCProtocol extends Disposable implements IRPCProtocol {
  5048. try {
  5049. return Promise.resolve(this._doInvokeHandler(rpcId, methodName, args));
  5050. } catch (err) {
  5051. + console.error('invokeHandler error:', err);
  5052. return Promise.reject(err);
  5053. }
  5054. }