| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468 |
- diff --git a/src/main.ts b/src/main.ts
- deleted file mode 100644
- index 1af3c941e00..00000000000
- --- a/src/main.ts
- +++ /dev/null
- @@ -1,719 +0,0 @@
- -/*---------------------------------------------------------------------------------------------
- - * Copyright (c) Microsoft Corporation. All rights reserved.
- - * Licensed under the MIT License. See License.txt in the project root for license information.
- - *--------------------------------------------------------------------------------------------*/
- -
- -import * as path from 'path';
- -import * as fs from 'original-fs';
- -import * as os from 'os';
- -import { performance } from 'perf_hooks';
- -import { configurePortable } from './bootstrap-node.js';
- -import { bootstrapESM } from './bootstrap-esm.js';
- -import { fileURLToPath } from 'url';
- -import { app, protocol, crashReporter, Menu, contentTracing } from 'electron';
- -import minimist from 'minimist';
- -import { product } from './bootstrap-meta.js';
- -import { parse } from './vs/base/common/jsonc.js';
- -import { getUserDataPath } from './vs/platform/environment/node/userDataPath.js';
- -import * as perf from './vs/base/common/performance.js';
- -import { resolveNLSConfiguration } from './vs/base/node/nls.js';
- -import { getUNCHost, addUNCHostToAllowlist } from './vs/base/node/unc.js';
- -import { INLSConfiguration } from './vs/nls.js';
- -import { NativeParsedArgs } from './vs/platform/environment/common/argv.js';
- -
- -const __dirname = path.dirname(fileURLToPath(import.meta.url));
- -
- -perf.mark('code/didStartMain');
- -
- -perf.mark('code/willLoadMainBundle', {
- - // When built, the main bundle is a single JS file with all
- - // dependencies inlined. As such, we mark `willLoadMainBundle`
- - // as the start of the main bundle loading process.
- - startTime: Math.floor(performance.timeOrigin)
- -});
- -perf.mark('code/didLoadMainBundle');
- -
- -// Enable portable support
- -const portable = configurePortable(product);
- -
- -const args = parseCLIArgs();
- -// Configure static command line arguments
- -const argvConfig = configureCommandlineSwitchesSync(args);
- -// Enable sandbox globally unless
- -// 1) disabled via command line using either
- -// `--no-sandbox` or `--disable-chromium-sandbox` argument.
- -// 2) argv.json contains `disable-chromium-sandbox: true`.
- -if (args['sandbox'] &&
- - !args['disable-chromium-sandbox'] &&
- - !argvConfig['disable-chromium-sandbox']) {
- - app.enableSandbox();
- -} else if (app.commandLine.hasSwitch('no-sandbox') &&
- - !app.commandLine.hasSwitch('disable-gpu-sandbox')) {
- - // Disable GPU sandbox whenever --no-sandbox is used.
- - app.commandLine.appendSwitch('disable-gpu-sandbox');
- -} else {
- - app.commandLine.appendSwitch('no-sandbox');
- - app.commandLine.appendSwitch('disable-gpu-sandbox');
- -}
- -
- -// Set userData path before app 'ready' event
- -const userDataPath = getUserDataPath(args, product.nameShort ?? 'code-oss-dev');
- -if (process.platform === 'win32') {
- - const userDataUNCHost = getUNCHost(userDataPath);
- - if (userDataUNCHost) {
- - addUNCHostToAllowlist(userDataUNCHost); // enables to use UNC paths in userDataPath
- - }
- -}
- -app.setPath('userData', userDataPath);
- -
- -// Resolve code cache path
- -const codeCachePath = getCodeCachePath();
- -
- -// Disable default menu (https://github.com/electron/electron/issues/35512)
- -Menu.setApplicationMenu(null);
- -
- -// Configure crash reporter
- -perf.mark('code/willStartCrashReporter');
- -// If a crash-reporter-directory is specified we store the crash reports
- -// in the specified directory and don't upload them to the crash server.
- -//
- -// Appcenter crash reporting is enabled if
- -// * enable-crash-reporter runtime argument is set to 'true'
- -// * --disable-crash-reporter command line parameter is not set
- -//
- -// Disable crash reporting in all other cases.
- -if (args['crash-reporter-directory'] || (argvConfig['enable-crash-reporter'] && !args['disable-crash-reporter'])) {
- - configureCrashReporter();
- -}
- -perf.mark('code/didStartCrashReporter');
- -
- -// Set logs path before app 'ready' event if running portable
- -// to ensure that no 'logs' folder is created on disk at a
- -// location outside of the portable directory
- -// (https://github.com/microsoft/vscode/issues/56651)
- -if (portable && portable.isPortable) {
- - app.setAppLogsPath(path.join(userDataPath, 'logs'));
- -}
- -
- -// Register custom schemes with privileges
- -protocol.registerSchemesAsPrivileged([
- - {
- - scheme: 'vscode-webview',
- - privileges: { standard: true, secure: true, supportFetchAPI: true, corsEnabled: true, allowServiceWorkers: true, codeCache: true }
- - },
- - {
- - scheme: 'vscode-file',
- - privileges: { secure: true, standard: true, supportFetchAPI: true, corsEnabled: true, codeCache: true }
- - }
- -]);
- -
- -// Global app listeners
- -registerListeners();
- -
- -/**
- - * We can resolve the NLS configuration early if it is defined
- - * in argv.json before `app.ready` event. Otherwise we can only
- - * resolve NLS after `app.ready` event to resolve the OS locale.
- - */
- -let nlsConfigurationPromise: Promise<INLSConfiguration> | undefined = undefined;
- -
- -// Use the most preferred OS language for language recommendation.
- -// The API might return an empty array on Linux, such as when
- -// the 'C' locale is the user's only configured locale.
- -// No matter the OS, if the array is empty, default back to 'en'.
- -const osLocale = processZhLocale((app.getPreferredSystemLanguages()?.[0] ?? 'en').toLowerCase());
- -const userLocale = getUserDefinedLocale(argvConfig);
- -if (userLocale) {
- - nlsConfigurationPromise = resolveNLSConfiguration({
- - userLocale,
- - osLocale,
- - commit: product.commit,
- - userDataPath,
- - nlsMetadataPath: __dirname
- - });
- -}
- -
- -// Pass in the locale to Electron so that the
- -// Windows Control Overlay is rendered correctly on Windows.
- -// For now, don't pass in the locale on macOS due to
- -// https://github.com/microsoft/vscode/issues/167543.
- -// If the locale is `qps-ploc`, the Microsoft
- -// Pseudo Language Language Pack is being used.
- -// In that case, use `en` as the Electron locale.
- -
- -if (process.platform === 'win32' || process.platform === 'linux') {
- - const electronLocale = (!userLocale || userLocale === 'qps-ploc') ? 'en' : userLocale;
- - app.commandLine.appendSwitch('lang', electronLocale);
- -}
- -
- -// Load our code once ready
- -app.once('ready', function () {
- - if (args['trace']) {
- - let traceOptions: Electron.TraceConfig | Electron.TraceCategoriesAndOptions;
- - if (args['trace-memory-infra']) {
- - const customCategories = args['trace-category-filter']?.split(',') || [];
- - customCategories.push('disabled-by-default-memory-infra', 'disabled-by-default-memory-infra.v8.code_stats');
- - traceOptions = {
- - included_categories: customCategories,
- - excluded_categories: ['*'],
- - memory_dump_config: {
- - allowed_dump_modes: ['light', 'detailed'],
- - triggers: [
- - {
- - type: 'periodic_interval',
- - mode: 'detailed',
- - min_time_between_dumps_ms: 10000
- - },
- - {
- - type: 'periodic_interval',
- - mode: 'light',
- - min_time_between_dumps_ms: 1000
- - }
- - ]
- - }
- - };
- - } else {
- - traceOptions = {
- - categoryFilter: args['trace-category-filter'] || '*',
- - traceOptions: args['trace-options'] || 'record-until-full,enable-sampling'
- - };
- - }
- -
- - contentTracing.startRecording(traceOptions).finally(() => onReady());
- - } else {
- - onReady();
- - }
- -});
- -
- -async function onReady() {
- - perf.mark('code/mainAppReady');
- -
- - try {
- - const [, nlsConfig] = await Promise.all([
- - mkdirpIgnoreError(codeCachePath),
- - resolveNlsConfiguration()
- - ]);
- -
- - await startup(codeCachePath, nlsConfig);
- - } catch (error) {
- - console.error(error);
- - }
- -}
- -
- -/**
- - * Main startup routine
- - */
- -async function startup(codeCachePath: string | undefined, nlsConfig: INLSConfiguration): Promise<void> {
- - process.env['VSCODE_NLS_CONFIG'] = JSON.stringify(nlsConfig);
- - process.env['VSCODE_CODE_CACHE_PATH'] = codeCachePath || '';
- -
- - // Bootstrap ESM
- - await bootstrapESM();
- -
- - // Load Main
- - await import('./vs/code/electron-main/main.js');
- - perf.mark('code/didRunMainBundle');
- -}
- -
- -function configureCommandlineSwitchesSync(cliArgs: NativeParsedArgs) {
- - const SUPPORTED_ELECTRON_SWITCHES = [
- -
- - // alias from us for --disable-gpu
- - 'disable-hardware-acceleration',
- -
- - // override for the color profile to use
- - 'force-color-profile',
- -
- - // disable LCD font rendering, a Chromium flag
- - 'disable-lcd-text',
- -
- - // bypass any specified proxy for the given semi-colon-separated list of hosts
- - 'proxy-bypass-list'
- - ];
- -
- - if (process.platform === 'linux') {
- -
- - // Force enable screen readers on Linux via this flag
- - SUPPORTED_ELECTRON_SWITCHES.push('force-renderer-accessibility');
- -
- - // override which password-store is used on Linux
- - SUPPORTED_ELECTRON_SWITCHES.push('password-store');
- - }
- -
- - const SUPPORTED_MAIN_PROCESS_SWITCHES = [
- -
- - // Persistently enable proposed api via argv.json: https://github.com/microsoft/vscode/issues/99775
- - 'enable-proposed-api',
- -
- - // Log level to use. Default is 'info'. Allowed values are 'error', 'warn', 'info', 'debug', 'trace', 'off'.
- - 'log-level',
- -
- - // Use an in-memory storage for secrets
- - 'use-inmemory-secretstorage'
- - ];
- -
- - // Read argv config
- - const argvConfig = readArgvConfigSync();
- -
- - Object.keys(argvConfig).forEach(argvKey => {
- - const argvValue = argvConfig[argvKey];
- -
- - // Append Electron flags to Electron
- - if (SUPPORTED_ELECTRON_SWITCHES.indexOf(argvKey) !== -1) {
- - if (argvValue === true || argvValue === 'true') {
- - if (argvKey === 'disable-hardware-acceleration') {
- - app.disableHardwareAcceleration(); // needs to be called explicitly
- - } else {
- - app.commandLine.appendSwitch(argvKey);
- - }
- - } else if (typeof argvValue === 'string' && argvValue) {
- - if (argvKey === 'password-store') {
- - // Password store
- - // TODO@TylerLeonhardt: Remove this migration in 3 months
- - let migratedArgvValue = argvValue;
- - if (argvValue === 'gnome' || argvValue === 'gnome-keyring') {
- - migratedArgvValue = 'gnome-libsecret';
- - }
- - app.commandLine.appendSwitch(argvKey, migratedArgvValue);
- - } else {
- - app.commandLine.appendSwitch(argvKey, argvValue);
- - }
- - }
- - }
- -
- - // Append main process flags to process.argv
- - else if (SUPPORTED_MAIN_PROCESS_SWITCHES.indexOf(argvKey) !== -1) {
- - switch (argvKey) {
- - case 'enable-proposed-api':
- - if (Array.isArray(argvValue)) {
- - argvValue.forEach(id => id && typeof id === 'string' && process.argv.push('--enable-proposed-api', id));
- - } else {
- - console.error(`Unexpected value for \`enable-proposed-api\` in argv.json. Expected array of extension ids.`);
- - }
- - break;
- -
- - case 'log-level':
- - if (typeof argvValue === 'string') {
- - process.argv.push('--log', argvValue);
- - } else if (Array.isArray(argvValue)) {
- - for (const value of argvValue) {
- - process.argv.push('--log', value);
- - }
- - }
- - break;
- -
- - case 'use-inmemory-secretstorage':
- - if (argvValue) {
- - process.argv.push('--use-inmemory-secretstorage');
- - }
- - break;
- - }
- - }
- - });
- -
- - // Following features are enabled from the runtime:
- - // `DocumentPolicyIncludeJSCallStacksInCrashReports` - https://www.electronjs.org/docs/latest/api/web-frame-main#framecollectjavascriptcallstack-experimental
- - // `EarlyEstablishGpuChannel` - Refs https://issues.chromium.org/issues/40208065
- - // `EstablishGpuChannelAsync` - Refs https://issues.chromium.org/issues/40208065
- - const featuresToEnable =
- - `DocumentPolicyIncludeJSCallStacksInCrashReports,EarlyEstablishGpuChannel,EstablishGpuChannelAsync,${app.commandLine.getSwitchValue('enable-features')}`;
- - app.commandLine.appendSwitch('enable-features', featuresToEnable);
- -
- - // Following features are disabled from the runtime:
- - // `CalculateNativeWinOcclusion` - Disable native window occlusion tracker (https://groups.google.com/a/chromium.org/g/embedder-dev/c/ZF3uHHyWLKw/m/VDN2hDXMAAAJ)
- - const featuresToDisable =
- - `CalculateNativeWinOcclusion,${app.commandLine.getSwitchValue('disable-features')}`;
- - app.commandLine.appendSwitch('disable-features', featuresToDisable);
- -
- - // Blink features to configure.
- - // `FontMatchingCTMigration` - Siwtch font matching on macOS to Appkit (Refs https://github.com/microsoft/vscode/issues/224496#issuecomment-2270418470).
- - // `StandardizedBrowserZoom` - Disable zoom adjustment for bounding box (https://github.com/microsoft/vscode/issues/232750#issuecomment-2459495394)
- - const blinkFeaturesToDisable =
- - `FontMatchingCTMigration,StandardizedBrowserZoom,${app.commandLine.getSwitchValue('disable-blink-features')}`;
- - app.commandLine.appendSwitch('disable-blink-features', blinkFeaturesToDisable);
- -
- - // Support JS Flags
- - const jsFlags = getJSFlags(cliArgs);
- - if (jsFlags) {
- - app.commandLine.appendSwitch('js-flags', jsFlags);
- - }
- -
- - // Use portal version 4 that supports current_folder option
- - // to address https://github.com/microsoft/vscode/issues/213780
- - // Runtime sets the default version to 3, refs https://github.com/electron/electron/pull/44426
- - app.commandLine.appendSwitch('xdg-portal-required-version', '4');
- -
- - return argvConfig;
- -}
- -
- -interface IArgvConfig {
- - [key: string]: string | string[] | boolean | undefined;
- - readonly locale?: string;
- - readonly 'disable-lcd-text'?: boolean;
- - readonly 'proxy-bypass-list'?: string;
- - readonly 'disable-hardware-acceleration'?: boolean;
- - readonly 'force-color-profile'?: string;
- - readonly 'enable-crash-reporter'?: boolean;
- - readonly 'crash-reporter-id'?: string;
- - readonly 'enable-proposed-api'?: string[];
- - readonly 'log-level'?: string | string[];
- - readonly 'disable-chromium-sandbox'?: boolean;
- - readonly 'use-inmemory-secretstorage'?: boolean;
- -}
- -
- -function readArgvConfigSync(): IArgvConfig {
- -
- - // Read or create the argv.json config file sync before app('ready')
- - const argvConfigPath = getArgvConfigPath();
- - let argvConfig: IArgvConfig | undefined = undefined;
- - try {
- - argvConfig = parse(fs.readFileSync(argvConfigPath).toString());
- - } catch (error) {
- - if (error && error.code === 'ENOENT') {
- - createDefaultArgvConfigSync(argvConfigPath);
- - } else {
- - console.warn(`Unable to read argv.json configuration file in ${argvConfigPath}, falling back to defaults (${error})`);
- - }
- - }
- -
- - // Fallback to default
- - if (!argvConfig) {
- - argvConfig = {};
- - }
- -
- - return argvConfig;
- -}
- -
- -function createDefaultArgvConfigSync(argvConfigPath: string): void {
- - try {
- -
- - // Ensure argv config parent exists
- - const argvConfigPathDirname = path.dirname(argvConfigPath);
- - if (!fs.existsSync(argvConfigPathDirname)) {
- - fs.mkdirSync(argvConfigPathDirname);
- - }
- -
- - // Default argv content
- - const defaultArgvConfigContent = [
- - '// This configuration file allows you to pass permanent command line arguments to VS Code.',
- - '// Only a subset of arguments is currently supported to reduce the likelihood of breaking',
- - '// the installation.',
- - '//',
- - '// PLEASE DO NOT CHANGE WITHOUT UNDERSTANDING THE IMPACT',
- - '//',
- - '// NOTE: Changing this file requires a restart of VS Code.',
- - '{',
- - ' // Use software rendering instead of hardware accelerated rendering.',
- - ' // This can help in cases where you see rendering issues in VS Code.',
- - ' // "disable-hardware-acceleration": true',
- - '}'
- - ];
- -
- - // Create initial argv.json with default content
- - fs.writeFileSync(argvConfigPath, defaultArgvConfigContent.join('\n'));
- - } catch (error) {
- - console.error(`Unable to create argv.json configuration file in ${argvConfigPath}, falling back to defaults (${error})`);
- - }
- -}
- -
- -function getArgvConfigPath(): string {
- - const vscodePortable = process.env['VSCODE_PORTABLE'];
- - if (vscodePortable) {
- - return path.join(vscodePortable, 'argv.json');
- - }
- -
- - let dataFolderName = product.dataFolderName;
- - if (process.env['VSCODE_DEV']) {
- - dataFolderName = `${dataFolderName}-dev`;
- - }
- -
- - return path.join(os.homedir(), dataFolderName!, 'argv.json');
- -}
- -
- -function configureCrashReporter(): void {
- - let crashReporterDirectory = args['crash-reporter-directory'];
- - let submitURL = '';
- - if (crashReporterDirectory) {
- - crashReporterDirectory = path.normalize(crashReporterDirectory);
- -
- - if (!path.isAbsolute(crashReporterDirectory)) {
- - console.error(`The path '${crashReporterDirectory}' specified for --crash-reporter-directory must be absolute.`);
- - app.exit(1);
- - }
- -
- - if (!fs.existsSync(crashReporterDirectory)) {
- - try {
- - fs.mkdirSync(crashReporterDirectory, { recursive: true });
- - } catch (error) {
- - console.error(`The path '${crashReporterDirectory}' specified for --crash-reporter-directory does not seem to exist or cannot be created.`);
- - app.exit(1);
- - }
- - }
- -
- - // Crashes are stored in the crashDumps directory by default, so we
- - // need to change that directory to the provided one
- - console.log(`Found --crash-reporter-directory argument. Setting crashDumps directory to be '${crashReporterDirectory}'`);
- - app.setPath('crashDumps', crashReporterDirectory);
- - }
- -
- - // Otherwise we configure the crash reporter from product.json
- - else {
- - const appCenter = product.appCenter;
- - if (appCenter) {
- - const isWindows = (process.platform === 'win32');
- - const isLinux = (process.platform === 'linux');
- - const isDarwin = (process.platform === 'darwin');
- - const crashReporterId = argvConfig['crash-reporter-id'];
- - const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
- - if (crashReporterId && uuidPattern.test(crashReporterId)) {
- - if (isWindows) {
- - switch (process.arch) {
- - case 'x64':
- - submitURL = appCenter['win32-x64'];
- - break;
- - case 'arm64':
- - submitURL = appCenter['win32-arm64'];
- - break;
- - }
- - } else if (isDarwin) {
- - if (product.darwinUniversalAssetId) {
- - submitURL = appCenter['darwin-universal'];
- - } else {
- - switch (process.arch) {
- - case 'x64':
- - submitURL = appCenter['darwin'];
- - break;
- - case 'arm64':
- - submitURL = appCenter['darwin-arm64'];
- - break;
- - }
- - }
- - } else if (isLinux) {
- - submitURL = appCenter['linux-x64'];
- - }
- - submitURL = submitURL.concat('&uid=', crashReporterId, '&iid=', crashReporterId, '&sid=', crashReporterId);
- - // Send the id for child node process that are explicitly starting crash reporter.
- - // For vscode this is ExtensionHost process currently.
- - const argv = process.argv;
- - const endOfArgsMarkerIndex = argv.indexOf('--');
- - if (endOfArgsMarkerIndex === -1) {
- - argv.push('--crash-reporter-id', crashReporterId);
- - } else {
- - // if the we have an argument "--" (end of argument marker)
- - // we cannot add arguments at the end. rather, we add
- - // arguments before the "--" marker.
- - argv.splice(endOfArgsMarkerIndex, 0, '--crash-reporter-id', crashReporterId);
- - }
- - }
- - }
- - }
- -
- - // Start crash reporter for all processes
- - const productName = (product.crashReporter ? product.crashReporter.productName : undefined) || product.nameShort;
- - const companyName = (product.crashReporter ? product.crashReporter.companyName : undefined) || 'Microsoft';
- - const uploadToServer = Boolean(!process.env['VSCODE_DEV'] && submitURL && !crashReporterDirectory);
- - crashReporter.start({
- - companyName,
- - productName: process.env['VSCODE_DEV'] ? `${productName} Dev` : productName,
- - submitURL,
- - uploadToServer,
- - compress: true
- - });
- -}
- -
- -function getJSFlags(cliArgs: NativeParsedArgs): string | null {
- - const jsFlags: string[] = [];
- -
- - // Add any existing JS flags we already got from the command line
- - if (cliArgs['js-flags']) {
- - jsFlags.push(cliArgs['js-flags']);
- - }
- -
- - if (process.platform === 'linux') {
- - // Fix cppgc crash on Linux with 16KB page size.
- - // Refs https://issues.chromium.org/issues/378017037
- - // The fix from https://github.com/electron/electron/commit/6c5b2ef55e08dc0bede02384747549c1eadac0eb
- - // only affects non-renderer process.
- - // The following will ensure that the flag will be
- - // applied to the renderer process as well.
- - // TODO(deepak1556): Remove this once we update to
- - // Chromium >= 134.
- - jsFlags.push('--nodecommit_pooled_pages');
- - }
- -
- - return jsFlags.length > 0 ? jsFlags.join(' ') : null;
- -}
- -
- -function parseCLIArgs(): NativeParsedArgs {
- - return minimist(process.argv, {
- - string: [
- - 'user-data-dir',
- - 'locale',
- - 'js-flags',
- - 'crash-reporter-directory'
- - ],
- - boolean: [
- - 'disable-chromium-sandbox',
- - ],
- - default: {
- - 'sandbox': true
- - },
- - alias: {
- - 'no-sandbox': 'sandbox'
- - }
- - });
- -}
- -
- -function registerListeners(): void {
- -
- - /**
- - * macOS: when someone drops a file to the not-yet running VSCode, the open-file event fires even before
- - * the app-ready event. We listen very early for open-file and remember this upon startup as path to open.
- - */
- - const macOpenFiles: string[] = [];
- - (globalThis as any)['macOpenFiles'] = macOpenFiles;
- - app.on('open-file', function (event, path) {
- - macOpenFiles.push(path);
- - });
- -
- - /**
- - * macOS: react to open-url requests.
- - */
- - const openUrls: string[] = [];
- - const onOpenUrl =
- - function (event: { preventDefault: () => void }, url: string) {
- - event.preventDefault();
- -
- - openUrls.push(url);
- - };
- -
- - app.on('will-finish-launching', function () {
- - app.on('open-url', onOpenUrl);
- - });
- -
- - (globalThis as any)['getOpenUrls'] = function () {
- - app.removeListener('open-url', onOpenUrl);
- -
- - return openUrls;
- - };
- -}
- -
- -function getCodeCachePath(): string | undefined {
- -
- - // explicitly disabled via CLI args
- - if (process.argv.indexOf('--no-cached-data') > 0) {
- - return undefined;
- - }
- -
- - // running out of sources
- - if (process.env['VSCODE_DEV']) {
- - return undefined;
- - }
- -
- - // require commit id
- - const commit = product.commit;
- - if (!commit) {
- - return undefined;
- - }
- -
- - return path.join(userDataPath, 'CachedData', commit);
- -}
- -
- -async function mkdirpIgnoreError(dir: string | undefined): Promise<string | undefined> {
- - if (typeof dir === 'string') {
- - try {
- - await fs.promises.mkdir(dir, { recursive: true });
- -
- - return dir;
- - } catch (error) {
- - // ignore
- - }
- - }
- -
- - return undefined;
- -}
- -
- -//#region NLS Support
- -
- -function processZhLocale(appLocale: string): string {
- - if (appLocale.startsWith('zh')) {
- - const region = appLocale.split('-')[1];
- -
- - // On Windows and macOS, Chinese languages returned by
- - // app.getPreferredSystemLanguages() start with zh-hans
- - // for Simplified Chinese or zh-hant for Traditional Chinese,
- - // so we can easily determine whether to use Simplified or Traditional.
- - // However, on Linux, Chinese languages returned by that same API
- - // are of the form zh-XY, where XY is a country code.
- - // For China (CN), Singapore (SG), and Malaysia (MY)
- - // country codes, assume they use Simplified Chinese.
- - // For other cases, assume they use Traditional.
- - if (['hans', 'cn', 'sg', 'my'].includes(region)) {
- - return 'zh-cn';
- - }
- -
- - return 'zh-tw';
- - }
- -
- - return appLocale;
- -}
- -
- -/**
- - * Resolve the NLS configuration
- - */
- -async function resolveNlsConfiguration(): Promise<INLSConfiguration> {
- -
- - // First, we need to test a user defined locale.
- - // If it fails we try the app locale.
- - // If that fails we fall back to English.
- -
- - const nlsConfiguration = nlsConfigurationPromise ? await nlsConfigurationPromise : undefined;
- - if (nlsConfiguration) {
- - return nlsConfiguration;
- - }
- -
- - // Try to use the app locale which is only valid
- - // after the app ready event has been fired.
- -
- - let userLocale = app.getLocale();
- - if (!userLocale) {
- - return {
- - userLocale: 'en',
- - osLocale,
- - resolvedLanguage: 'en',
- - defaultMessagesFile: path.join(__dirname, 'nls.messages.json'),
- -
- - // NLS: below 2 are a relic from old times only used by vscode-nls and deprecated
- - locale: 'en',
- - availableLanguages: {}
- - };
- - }
- -
- - // See above the comment about the loader and case sensitiveness
- - userLocale = processZhLocale(userLocale.toLowerCase());
- -
- - return resolveNLSConfiguration({
- - userLocale,
- - osLocale,
- - commit: product.commit,
- - userDataPath,
- - nlsMetadataPath: __dirname
- - });
- -}
- -
- -/**
- - * Language tags are case insensitive however an ESM loader is case sensitive
- - * To make this work on case preserving & insensitive FS we do the following:
- - * the language bundles have lower case language tags and we always lower case
- - * the locale we receive from the user or OS.
- - */
- -function getUserDefinedLocale(argvConfig: IArgvConfig): string | undefined {
- - const locale = args['locale'];
- - if (locale) {
- - return locale.toLowerCase(); // a directly provided --locale always wins
- - }
- -
- - return typeof argvConfig?.locale === 'string' ? argvConfig.locale.toLowerCase() : undefined;
- -}
- -
- -//#endregion
- diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts
- index 7227aba24f3..af3d09a5b2d 100644
- --- a/src/vs/base/browser/dom.ts
- +++ b/src/vs/base/browser/dom.ts
- @@ -3,28 +3,28 @@
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
-
- -import * as browser from './browser.js';
- -import { BrowserFeatures } from './canIUse.js';
- -import { IKeyboardEvent, StandardKeyboardEvent } from './keyboardEvent.js';
- -import { IMouseEvent, StandardMouseEvent } from './mouseEvent.js';
- -import { AbstractIdleValue, IntervalTimer, TimeoutTimer, _runWhenIdle, IdleDeadline } from '../common/async.js';
- -import { onUnexpectedError } from '../common/errors.js';
- -import * as event from '../common/event.js';
- -import dompurify from './dompurify/dompurify.js';
- -import { KeyCode } from '../common/keyCodes.js';
- -import { Disposable, DisposableStore, IDisposable, toDisposable } from '../common/lifecycle.js';
- -import { RemoteAuthorities, Schemas } from '../common/network.js';
- -import * as platform from '../common/platform.js';
- -import { URI } from '../common/uri.js';
- -import { hash } from '../common/hash.js';
- -import { CodeWindow, ensureCodeWindow, mainWindow } from './window.js';
- -import { isPointWithinTriangle } from '../common/numbers.js';
- -export * from './domImpl/domObservable.js';
- -export * from './domImpl/n.js';
- +import * as browser from "./browser.js"
- +import { BrowserFeatures } from "./canIUse.js"
- +import { IKeyboardEvent, StandardKeyboardEvent } from "./keyboardEvent.js"
- +import { IMouseEvent, StandardMouseEvent } from "./mouseEvent.js"
- +import { AbstractIdleValue, IntervalTimer, TimeoutTimer, _runWhenIdle, IdleDeadline } from "../common/async.js"
- +import { onUnexpectedError } from "../common/errors.js"
- +import * as event from "../common/event.js"
- +import dompurify from "./dompurify/dompurify.js"
- +import { KeyCode } from "../common/keyCodes.js"
- +import { Disposable, DisposableStore, IDisposable, toDisposable } from "../common/lifecycle.js"
- +import { RemoteAuthorities, Schemas } from "../common/network.js"
- +import * as platform from "../common/platform.js"
- +import { URI } from "../common/uri.js"
- +import { hash } from "../common/hash.js"
- +import { CodeWindow, ensureCodeWindow, mainWindow } from "./window.js"
- +import { isPointWithinTriangle } from "../common/numbers.js"
- +export * from "./domImpl/domObservable.js"
- +export * from "./domImpl/n.js"
-
- export interface IRegisteredCodeWindow {
- - readonly window: CodeWindow;
- - readonly disposables: DisposableStore;
- + readonly window: CodeWindow
- + readonly disposables: DisposableStore
- }
-
- //# region Multi-Window Support Utilities
- @@ -40,24 +40,24 @@ export const {
- hasWindow,
- onDidRegisterWindow,
- onWillUnregisterWindow,
- - onDidUnregisterWindow
- + onDidUnregisterWindow,
- } = (function () {
- - const windows = new Map<number, IRegisteredCodeWindow>();
- + const windows = new Map<number, IRegisteredCodeWindow>()
-
- - ensureCodeWindow(mainWindow, 1);
- - const mainWindowRegistration = { window: mainWindow, disposables: new DisposableStore() };
- - windows.set(mainWindow.vscodeWindowId, mainWindowRegistration);
- + ensureCodeWindow(mainWindow, 1)
- + const mainWindowRegistration = { window: mainWindow, disposables: new DisposableStore() }
- + windows.set(mainWindow.vscodeWindowId, mainWindowRegistration)
-
- - const onDidRegisterWindow = new event.Emitter<IRegisteredCodeWindow>();
- - const onDidUnregisterWindow = new event.Emitter<CodeWindow>();
- - const onWillUnregisterWindow = new event.Emitter<CodeWindow>();
- + const onDidRegisterWindow = new event.Emitter<IRegisteredCodeWindow>()
- + const onDidUnregisterWindow = new event.Emitter<CodeWindow>()
- + const onWillUnregisterWindow = new event.Emitter<CodeWindow>()
-
- - function getWindowById(windowId: number): IRegisteredCodeWindow | undefined;
- - function getWindowById(windowId: number | undefined, fallbackToMain: true): IRegisteredCodeWindow;
- + function getWindowById(windowId: number): IRegisteredCodeWindow | undefined
- + function getWindowById(windowId: number | undefined, fallbackToMain: true): IRegisteredCodeWindow
- function getWindowById(windowId: number | undefined, fallbackToMain?: boolean): IRegisteredCodeWindow | undefined {
- - const window = typeof windowId === 'number' ? windows.get(windowId) : undefined;
- + const window = typeof windowId === "number" ? windows.get(windowId) : undefined
-
- - return window ?? (fallbackToMain ? mainWindowRegistration : undefined);
- + return window ?? (fallbackToMain ? mainWindowRegistration : undefined)
- }
-
- return {
- @@ -66,161 +66,230 @@ export const {
- onDidUnregisterWindow: onDidUnregisterWindow.event,
- registerWindow(window: CodeWindow): IDisposable {
- if (windows.has(window.vscodeWindowId)) {
- - return Disposable.None;
- + return Disposable.None
- }
-
- - const disposables = new DisposableStore();
- + const disposables = new DisposableStore()
-
- const registeredWindow = {
- window,
- - disposables: disposables.add(new DisposableStore())
- - };
- - windows.set(window.vscodeWindowId, registeredWindow);
- + disposables: disposables.add(new DisposableStore()),
- + }
- + windows.set(window.vscodeWindowId, registeredWindow)
-
- - disposables.add(toDisposable(() => {
- - windows.delete(window.vscodeWindowId);
- - onDidUnregisterWindow.fire(window);
- - }));
- + disposables.add(
- + toDisposable(() => {
- + windows.delete(window.vscodeWindowId)
- + onDidUnregisterWindow.fire(window)
- + }),
- + )
-
- - disposables.add(addDisposableListener(window, EventType.BEFORE_UNLOAD, () => {
- - onWillUnregisterWindow.fire(window);
- - }));
- + disposables.add(
- + addDisposableListener(window, EventType.BEFORE_UNLOAD, () => {
- + onWillUnregisterWindow.fire(window)
- + }),
- + )
-
- - onDidRegisterWindow.fire(registeredWindow);
- + onDidRegisterWindow.fire(registeredWindow)
-
- - return disposables;
- + return disposables
- },
- getWindows(): Iterable<IRegisteredCodeWindow> {
- - return windows.values();
- + return windows.values()
- },
- getWindowsCount(): number {
- - return windows.size;
- + return windows.size
- },
- getWindowId(targetWindow: Window): number {
- - return (targetWindow as CodeWindow).vscodeWindowId;
- + return (targetWindow as CodeWindow).vscodeWindowId
- },
- hasWindow(windowId: number): boolean {
- - return windows.has(windowId);
- + return windows.has(windowId)
- },
- getWindowById,
- getWindow(e: Node | UIEvent | undefined | null): CodeWindow {
- - const candidateNode = e as Node | undefined | null;
- + const candidateNode = e as Node | undefined | null
- if (candidateNode?.ownerDocument?.defaultView) {
- - return candidateNode.ownerDocument.defaultView.window as CodeWindow;
- + return candidateNode.ownerDocument.defaultView.window as CodeWindow
- }
-
- - const candidateEvent = e as UIEvent | undefined | null;
- + const candidateEvent = e as UIEvent | undefined | null
- if (candidateEvent?.view) {
- - return candidateEvent.view.window as CodeWindow;
- + return candidateEvent.view.window as CodeWindow
- }
-
- - return mainWindow;
- + return mainWindow
- },
- getDocument(e: Node | UIEvent | undefined | null): Document {
- - const candidateNode = e as Node | undefined | null;
- - return getWindow(candidateNode).document;
- - }
- - };
- -})();
- + const candidateNode = e as Node | undefined | null
- + return getWindow(candidateNode).document
- + },
- + }
- +})()
-
- //#endregion
-
- export function clearNode(node: HTMLElement): void {
- while (node.firstChild) {
- - node.firstChild.remove();
- + node.firstChild.remove()
- }
- }
-
- class DomListener implements IDisposable {
- + private _handler: (e: any) => void
- + private _node: EventTarget
- + private readonly _type: string
- + private readonly _options: boolean | AddEventListenerOptions
-
- - private _handler: (e: any) => void;
- - private _node: EventTarget;
- - private readonly _type: string;
- - private readonly _options: boolean | AddEventListenerOptions;
- -
- - constructor(node: EventTarget, type: string, handler: (e: any) => void, options?: boolean | AddEventListenerOptions) {
- - this._node = node;
- - this._type = type;
- - this._handler = handler;
- - this._options = (options || false);
- - this._node.addEventListener(this._type, this._handler, this._options);
- + constructor(
- + node: EventTarget,
- + type: string,
- + handler: (e: any) => void,
- + options?: boolean | AddEventListenerOptions,
- + ) {
- + this._node = node
- + this._type = type
- + this._handler = handler
- + this._options = options || false
- + this._node.addEventListener(this._type, this._handler, this._options)
- }
-
- dispose(): void {
- if (!this._handler) {
- // Already disposed
- - return;
- + return
- }
-
- - this._node.removeEventListener(this._type, this._handler, this._options);
- + this._node.removeEventListener(this._type, this._handler, this._options)
-
- // Prevent leakers from holding on to the dom or handler func
- - this._node = null!;
- - this._handler = null!;
- - }
- -}
- -
- -export function addDisposableListener<K extends keyof GlobalEventHandlersEventMap>(node: EventTarget, type: K, handler: (event: GlobalEventHandlersEventMap[K]) => void, useCapture?: boolean): IDisposable;
- -export function addDisposableListener(node: EventTarget, type: string, handler: (event: any) => void, useCapture?: boolean): IDisposable;
- -export function addDisposableListener(node: EventTarget, type: string, handler: (event: any) => void, options: AddEventListenerOptions): IDisposable;
- -export function addDisposableListener(node: EventTarget, type: string, handler: (event: any) => void, useCaptureOrOptions?: boolean | AddEventListenerOptions): IDisposable {
- - return new DomListener(node, type, handler, useCaptureOrOptions);
- + this._node = null!
- + this._handler = null!
- + }
- +}
- +
- +export function addDisposableListener<K extends keyof GlobalEventHandlersEventMap>(
- + node: EventTarget,
- + type: K,
- + handler: (event: GlobalEventHandlersEventMap[K]) => void,
- + useCapture?: boolean,
- +): IDisposable
- +export function addDisposableListener(
- + node: EventTarget,
- + type: string,
- + handler: (event: any) => void,
- + useCapture?: boolean,
- +): IDisposable
- +export function addDisposableListener(
- + node: EventTarget,
- + type: string,
- + handler: (event: any) => void,
- + options: AddEventListenerOptions,
- +): IDisposable
- +export function addDisposableListener(
- + node: EventTarget,
- + type: string,
- + handler: (event: any) => void,
- + useCaptureOrOptions?: boolean | AddEventListenerOptions,
- +): IDisposable {
- + return new DomListener(node, type, handler, useCaptureOrOptions)
- }
-
- export interface IAddStandardDisposableListenerSignature {
- - (node: HTMLElement, type: 'click', handler: (event: IMouseEvent) => void, useCapture?: boolean): IDisposable;
- - (node: HTMLElement, type: 'mousedown', handler: (event: IMouseEvent) => void, useCapture?: boolean): IDisposable;
- - (node: HTMLElement, type: 'keydown', handler: (event: IKeyboardEvent) => void, useCapture?: boolean): IDisposable;
- - (node: HTMLElement, type: 'keypress', handler: (event: IKeyboardEvent) => void, useCapture?: boolean): IDisposable;
- - (node: HTMLElement, type: 'keyup', handler: (event: IKeyboardEvent) => void, useCapture?: boolean): IDisposable;
- - (node: HTMLElement, type: 'pointerdown', handler: (event: PointerEvent) => void, useCapture?: boolean): IDisposable;
- - (node: HTMLElement, type: 'pointermove', handler: (event: PointerEvent) => void, useCapture?: boolean): IDisposable;
- - (node: HTMLElement, type: 'pointerup', handler: (event: PointerEvent) => void, useCapture?: boolean): IDisposable;
- - (node: HTMLElement, type: string, handler: (event: any) => void, useCapture?: boolean): IDisposable;
- + (node: HTMLElement, type: "click", handler: (event: IMouseEvent) => void, useCapture?: boolean): IDisposable
- + (node: HTMLElement, type: "mousedown", handler: (event: IMouseEvent) => void, useCapture?: boolean): IDisposable
- + (node: HTMLElement, type: "keydown", handler: (event: IKeyboardEvent) => void, useCapture?: boolean): IDisposable
- + (node: HTMLElement, type: "keypress", handler: (event: IKeyboardEvent) => void, useCapture?: boolean): IDisposable
- + (node: HTMLElement, type: "keyup", handler: (event: IKeyboardEvent) => void, useCapture?: boolean): IDisposable
- + (node: HTMLElement, type: "pointerdown", handler: (event: PointerEvent) => void, useCapture?: boolean): IDisposable
- + (node: HTMLElement, type: "pointermove", handler: (event: PointerEvent) => void, useCapture?: boolean): IDisposable
- + (node: HTMLElement, type: "pointerup", handler: (event: PointerEvent) => void, useCapture?: boolean): IDisposable
- + (node: HTMLElement, type: string, handler: (event: any) => void, useCapture?: boolean): IDisposable
- }
- function _wrapAsStandardMouseEvent(targetWindow: Window, handler: (e: IMouseEvent) => void): (e: MouseEvent) => void {
- return function (e: MouseEvent) {
- - return handler(new StandardMouseEvent(targetWindow, e));
- - };
- + return handler(new StandardMouseEvent(targetWindow, e))
- + }
- }
- function _wrapAsStandardKeyboardEvent(handler: (e: IKeyboardEvent) => void): (e: KeyboardEvent) => void {
- return function (e: KeyboardEvent) {
- - return handler(new StandardKeyboardEvent(e));
- - };
- -}
- -export const addStandardDisposableListener: IAddStandardDisposableListenerSignature = function addStandardDisposableListener(node: HTMLElement, type: string, handler: (event: any) => void, useCapture?: boolean): IDisposable {
- - let wrapHandler = handler;
- -
- - if (type === 'click' || type === 'mousedown' || type === 'contextmenu') {
- - wrapHandler = _wrapAsStandardMouseEvent(getWindow(node), handler);
- - } else if (type === 'keydown' || type === 'keypress' || type === 'keyup') {
- - wrapHandler = _wrapAsStandardKeyboardEvent(handler);
- - }
- -
- - return addDisposableListener(node, type, wrapHandler, useCapture);
- -};
- -
- -export const addStandardDisposableGenericMouseDownListener = function addStandardDisposableListener(node: HTMLElement, handler: (event: any) => void, useCapture?: boolean): IDisposable {
- - const wrapHandler = _wrapAsStandardMouseEvent(getWindow(node), handler);
- -
- - return addDisposableGenericMouseDownListener(node, wrapHandler, useCapture);
- -};
- -
- -export const addStandardDisposableGenericMouseUpListener = function addStandardDisposableListener(node: HTMLElement, handler: (event: any) => void, useCapture?: boolean): IDisposable {
- - const wrapHandler = _wrapAsStandardMouseEvent(getWindow(node), handler);
- -
- - return addDisposableGenericMouseUpListener(node, wrapHandler, useCapture);
- -};
- -export function addDisposableGenericMouseDownListener(node: EventTarget, handler: (event: any) => void, useCapture?: boolean): IDisposable {
- - return addDisposableListener(node, platform.isIOS && BrowserFeatures.pointerEvents ? EventType.POINTER_DOWN : EventType.MOUSE_DOWN, handler, useCapture);
- -}
- -
- -export function addDisposableGenericMouseMoveListener(node: EventTarget, handler: (event: any) => void, useCapture?: boolean): IDisposable {
- - return addDisposableListener(node, platform.isIOS && BrowserFeatures.pointerEvents ? EventType.POINTER_MOVE : EventType.MOUSE_MOVE, handler, useCapture);
- -}
- + return handler(new StandardKeyboardEvent(e))
- + }
- +}
- +export const addStandardDisposableListener: IAddStandardDisposableListenerSignature =
- + function addStandardDisposableListener(
- + node: HTMLElement,
- + type: string,
- + handler: (event: any) => void,
- + useCapture?: boolean,
- + ): IDisposable {
- + let wrapHandler = handler
- +
- + if (type === "click" || type === "mousedown" || type === "contextmenu") {
- + wrapHandler = _wrapAsStandardMouseEvent(getWindow(node), handler)
- + } else if (type === "keydown" || type === "keypress" || type === "keyup") {
- + wrapHandler = _wrapAsStandardKeyboardEvent(handler)
- + }
-
- -export function addDisposableGenericMouseUpListener(node: EventTarget, handler: (event: any) => void, useCapture?: boolean): IDisposable {
- - return addDisposableListener(node, platform.isIOS && BrowserFeatures.pointerEvents ? EventType.POINTER_UP : EventType.MOUSE_UP, handler, useCapture);
- + return addDisposableListener(node, type, wrapHandler, useCapture)
- + }
- +
- +export const addStandardDisposableGenericMouseDownListener = function addStandardDisposableListener(
- + node: HTMLElement,
- + handler: (event: any) => void,
- + useCapture?: boolean,
- +): IDisposable {
- + const wrapHandler = _wrapAsStandardMouseEvent(getWindow(node), handler)
- +
- + return addDisposableGenericMouseDownListener(node, wrapHandler, useCapture)
- +}
- +
- +export const addStandardDisposableGenericMouseUpListener = function addStandardDisposableListener(
- + node: HTMLElement,
- + handler: (event: any) => void,
- + useCapture?: boolean,
- +): IDisposable {
- + const wrapHandler = _wrapAsStandardMouseEvent(getWindow(node), handler)
- +
- + return addDisposableGenericMouseUpListener(node, wrapHandler, useCapture)
- +}
- +export function addDisposableGenericMouseDownListener(
- + node: EventTarget,
- + handler: (event: any) => void,
- + useCapture?: boolean,
- +): IDisposable {
- + return addDisposableListener(
- + node,
- + platform.isIOS && BrowserFeatures.pointerEvents ? EventType.POINTER_DOWN : EventType.MOUSE_DOWN,
- + handler,
- + useCapture,
- + )
- +}
- +
- +export function addDisposableGenericMouseMoveListener(
- + node: EventTarget,
- + handler: (event: any) => void,
- + useCapture?: boolean,
- +): IDisposable {
- + return addDisposableListener(
- + node,
- + platform.isIOS && BrowserFeatures.pointerEvents ? EventType.POINTER_MOVE : EventType.MOUSE_MOVE,
- + handler,
- + useCapture,
- + )
- +}
- +
- +export function addDisposableGenericMouseUpListener(
- + node: EventTarget,
- + handler: (event: any) => void,
- + useCapture?: boolean,
- +): IDisposable {
- + return addDisposableListener(
- + node,
- + platform.isIOS && BrowserFeatures.pointerEvents ? EventType.POINTER_UP : EventType.MOUSE_UP,
- + handler,
- + useCapture,
- + )
- }
-
- /**
- @@ -242,8 +311,12 @@ export function addDisposableGenericMouseUpListener(node: EventTarget, handler:
- * [requestIdleCallback]: https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback
- * [setTimeout]: https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout
- */
- -export function runWhenWindowIdle(targetWindow: Window | typeof globalThis, callback: (idle: IdleDeadline) => void, timeout?: number): IDisposable {
- - return _runWhenIdle(targetWindow, callback, timeout);
- +export function runWhenWindowIdle(
- + targetWindow: Window | typeof globalThis,
- + callback: (idle: IdleDeadline) => void,
- + timeout?: number,
- +): IDisposable {
- + return _runWhenIdle(targetWindow, callback, timeout)
- }
-
- /**
- @@ -252,7 +325,7 @@ export function runWhenWindowIdle(targetWindow: Window | typeof globalThis, call
- */
- export class WindowIdleValue<T> extends AbstractIdleValue<T> {
- constructor(targetWindow: Window | typeof globalThis, executor: () => T) {
- - super(targetWindow, executor);
- + super(targetWindow, executor)
- }
- }
-
- @@ -262,299 +335,326 @@ export class WindowIdleValue<T> extends AbstractIdleValue<T> {
- * If currently in an animation frame, `runner` will be executed immediately.
- * @return token that can be used to cancel the scheduled runner (only if `runner` was not executed immediately).
- */
- -export let runAtThisOrScheduleAtNextAnimationFrame: (targetWindow: Window, runner: () => void, priority?: number) => IDisposable;
- +export let runAtThisOrScheduleAtNextAnimationFrame: (
- + targetWindow: Window,
- + runner: () => void,
- + priority?: number,
- +) => IDisposable
- /**
- * Schedule a callback to be run at the next animation frame.
- * This allows multiple parties to register callbacks that should run at the next animation frame.
- * If currently in an animation frame, `runner` will be executed at the next animation frame.
- * @return token that can be used to cancel the scheduled runner.
- */
- -export let scheduleAtNextAnimationFrame: (targetWindow: Window, runner: () => void, priority?: number) => IDisposable;
- -
- -export function disposableWindowInterval(targetWindow: Window, handler: () => void | boolean /* stop interval */ | Promise<unknown>, interval: number, iterations?: number): IDisposable {
- - let iteration = 0;
- +export let scheduleAtNextAnimationFrame: (targetWindow: Window, runner: () => void, priority?: number) => IDisposable
- +
- +export function disposableWindowInterval(
- + targetWindow: Window,
- + handler: () => void | boolean /* stop interval */ | Promise<unknown>,
- + interval: number,
- + iterations?: number,
- +): IDisposable {
- + let iteration = 0
- const timer = targetWindow.setInterval(() => {
- - iteration++;
- - if ((typeof iterations === 'number' && iteration >= iterations) || handler() === true) {
- - disposable.dispose();
- + iteration++
- + if ((typeof iterations === "number" && iteration >= iterations) || handler() === true) {
- + disposable.dispose()
- }
- - }, interval);
- + }, interval)
- const disposable = toDisposable(() => {
- - targetWindow.clearInterval(timer);
- - });
- - return disposable;
- + targetWindow.clearInterval(timer)
- + })
- + return disposable
- }
-
- export class WindowIntervalTimer extends IntervalTimer {
- -
- - private readonly defaultTarget?: Window & typeof globalThis;
- + private readonly defaultTarget?: Window & typeof globalThis
-
- /**
- *
- * @param node The optional node from which the target window is determined
- */
- constructor(node?: Node) {
- - super();
- - this.defaultTarget = node && getWindow(node);
- + super()
- + this.defaultTarget = node && getWindow(node)
- }
-
- override cancelAndSet(runner: () => void, interval: number, targetWindow?: Window & typeof globalThis): void {
- - return super.cancelAndSet(runner, interval, targetWindow ?? this.defaultTarget);
- + return super.cancelAndSet(runner, interval, targetWindow ?? this.defaultTarget)
- }
- }
-
- class AnimationFrameQueueItem implements IDisposable {
- -
- - private _runner: () => void;
- - public priority: number;
- - private _canceled: boolean;
- + private _runner: () => void
- + public priority: number
- + private _canceled: boolean
-
- constructor(runner: () => void, priority: number = 0) {
- - this._runner = runner;
- - this.priority = priority;
- - this._canceled = false;
- + this._runner = runner
- + this.priority = priority
- + this._canceled = false
- }
-
- dispose(): void {
- - this._canceled = true;
- + this._canceled = true
- }
-
- execute(): void {
- if (this._canceled) {
- - return;
- + return
- }
-
- try {
- - this._runner();
- + this._runner()
- } catch (e) {
- - onUnexpectedError(e);
- + onUnexpectedError(e)
- }
- }
-
- // Sort by priority (largest to lowest)
- static sort(a: AnimationFrameQueueItem, b: AnimationFrameQueueItem): number {
- - return b.priority - a.priority;
- + return b.priority - a.priority
- }
- }
-
- -(function () {
- +;(function () {
- /**
- * The runners scheduled at the next animation frame
- */
- - const NEXT_QUEUE = new Map<number /* window ID */, AnimationFrameQueueItem[]>();
- + const NEXT_QUEUE = new Map<number /* window ID */, AnimationFrameQueueItem[]>()
- /**
- * The runners scheduled at the current animation frame
- */
- - const CURRENT_QUEUE = new Map<number /* window ID */, AnimationFrameQueueItem[]>();
- + const CURRENT_QUEUE = new Map<number /* window ID */, AnimationFrameQueueItem[]>()
- /**
- * A flag to keep track if the native requestAnimationFrame was already called
- */
- - const animFrameRequested = new Map<number /* window ID */, boolean>();
- + const animFrameRequested = new Map<number /* window ID */, boolean>()
- /**
- * A flag to indicate if currently handling a native requestAnimationFrame callback
- */
- - const inAnimationFrameRunner = new Map<number /* window ID */, boolean>();
- + const inAnimationFrameRunner = new Map<number /* window ID */, boolean>()
-
- const animationFrameRunner = (targetWindowId: number) => {
- - animFrameRequested.set(targetWindowId, false);
- + animFrameRequested.set(targetWindowId, false)
-
- - const currentQueue = NEXT_QUEUE.get(targetWindowId) ?? [];
- - CURRENT_QUEUE.set(targetWindowId, currentQueue);
- - NEXT_QUEUE.set(targetWindowId, []);
- + const currentQueue = NEXT_QUEUE.get(targetWindowId) ?? []
- + CURRENT_QUEUE.set(targetWindowId, currentQueue)
- + NEXT_QUEUE.set(targetWindowId, [])
-
- - inAnimationFrameRunner.set(targetWindowId, true);
- + inAnimationFrameRunner.set(targetWindowId, true)
- while (currentQueue.length > 0) {
- - currentQueue.sort(AnimationFrameQueueItem.sort);
- - const top = currentQueue.shift()!;
- - top.execute();
- + currentQueue.sort(AnimationFrameQueueItem.sort)
- + const top = currentQueue.shift()!
- + top.execute()
- }
- - inAnimationFrameRunner.set(targetWindowId, false);
- - };
- + inAnimationFrameRunner.set(targetWindowId, false)
- + }
-
- scheduleAtNextAnimationFrame = (targetWindow: Window, runner: () => void, priority: number = 0) => {
- - const targetWindowId = getWindowId(targetWindow);
- - const item = new AnimationFrameQueueItem(runner, priority);
- + const targetWindowId = getWindowId(targetWindow)
- + const item = new AnimationFrameQueueItem(runner, priority)
-
- - let nextQueue = NEXT_QUEUE.get(targetWindowId);
- + let nextQueue = NEXT_QUEUE.get(targetWindowId)
- if (!nextQueue) {
- - nextQueue = [];
- - NEXT_QUEUE.set(targetWindowId, nextQueue);
- + nextQueue = []
- + NEXT_QUEUE.set(targetWindowId, nextQueue)
- }
- - nextQueue.push(item);
- + nextQueue.push(item)
-
- if (!animFrameRequested.get(targetWindowId)) {
- - animFrameRequested.set(targetWindowId, true);
- - targetWindow.requestAnimationFrame(() => animationFrameRunner(targetWindowId));
- + animFrameRequested.set(targetWindowId, true)
- + targetWindow.requestAnimationFrame(() => animationFrameRunner(targetWindowId))
- }
-
- - return item;
- - };
- + return item
- + }
-
- runAtThisOrScheduleAtNextAnimationFrame = (targetWindow: Window, runner: () => void, priority?: number) => {
- - const targetWindowId = getWindowId(targetWindow);
- + const targetWindowId = getWindowId(targetWindow)
- if (inAnimationFrameRunner.get(targetWindowId)) {
- - const item = new AnimationFrameQueueItem(runner, priority);
- - let currentQueue = CURRENT_QUEUE.get(targetWindowId);
- + const item = new AnimationFrameQueueItem(runner, priority)
- + let currentQueue = CURRENT_QUEUE.get(targetWindowId)
- if (!currentQueue) {
- - currentQueue = [];
- - CURRENT_QUEUE.set(targetWindowId, currentQueue);
- + currentQueue = []
- + CURRENT_QUEUE.set(targetWindowId, currentQueue)
- }
- - currentQueue.push(item);
- - return item;
- + currentQueue.push(item)
- + return item
- } else {
- - return scheduleAtNextAnimationFrame(targetWindow, runner, priority);
- + return scheduleAtNextAnimationFrame(targetWindow, runner, priority)
- }
- - };
- -})();
- + }
- +})()
-
- export function measure(targetWindow: Window, callback: () => void): IDisposable {
- - return scheduleAtNextAnimationFrame(targetWindow, callback, 10000 /* must be early */);
- + return scheduleAtNextAnimationFrame(targetWindow, callback, 10000 /* must be early */)
- }
-
- export function modify(targetWindow: Window, callback: () => void): IDisposable {
- - return scheduleAtNextAnimationFrame(targetWindow, callback, -10000 /* must be late */);
- + return scheduleAtNextAnimationFrame(targetWindow, callback, -10000 /* must be late */)
- }
-
- /**
- * Add a throttled listener. `handler` is fired at most every 8.33333ms or with the next animation frame (if browser supports it).
- */
- export interface IEventMerger<R, E> {
- - (lastEvent: R | null, currentEvent: E): R;
- + (lastEvent: R | null, currentEvent: E): R
- }
-
- -const MINIMUM_TIME_MS = 8;
- +const MINIMUM_TIME_MS = 8
- const DEFAULT_EVENT_MERGER: IEventMerger<Event, Event> = function (lastEvent: Event | null, currentEvent: Event) {
- - return currentEvent;
- -};
- + return currentEvent
- +}
-
- class TimeoutThrottledDomListener<R, E extends Event> extends Disposable {
- + constructor(
- + node: any,
- + type: string,
- + handler: (event: R) => void,
- + eventMerger: IEventMerger<R, E> = <any>DEFAULT_EVENT_MERGER,
- + minimumTimeMs: number = MINIMUM_TIME_MS,
- + ) {
- + super()
-
- - constructor(node: any, type: string, handler: (event: R) => void, eventMerger: IEventMerger<R, E> = <any>DEFAULT_EVENT_MERGER, minimumTimeMs: number = MINIMUM_TIME_MS) {
- - super();
- -
- - let lastEvent: R | null = null;
- - let lastHandlerTime = 0;
- - const timeout = this._register(new TimeoutTimer());
- + let lastEvent: R | null = null
- + let lastHandlerTime = 0
- + const timeout = this._register(new TimeoutTimer())
-
- const invokeHandler = () => {
- - lastHandlerTime = (new Date()).getTime();
- - handler(<R>lastEvent);
- - lastEvent = null;
- - };
- -
- - this._register(addDisposableListener(node, type, (e) => {
- + lastHandlerTime = new Date().getTime()
- + handler(<R>lastEvent)
- + lastEvent = null
- + }
-
- - lastEvent = eventMerger(lastEvent, e);
- - const elapsedTime = (new Date()).getTime() - lastHandlerTime;
- + this._register(
- + addDisposableListener(node, type, (e) => {
- + lastEvent = eventMerger(lastEvent, e)
- + const elapsedTime = new Date().getTime() - lastHandlerTime
-
- - if (elapsedTime >= minimumTimeMs) {
- - timeout.cancel();
- - invokeHandler();
- - } else {
- - timeout.setIfNotSet(invokeHandler, minimumTimeMs - elapsedTime);
- - }
- - }));
- + if (elapsedTime >= minimumTimeMs) {
- + timeout.cancel()
- + invokeHandler()
- + } else {
- + timeout.setIfNotSet(invokeHandler, minimumTimeMs - elapsedTime)
- + }
- + }),
- + )
- }
- }
-
- -export function addDisposableThrottledListener<R, E extends Event = Event>(node: any, type: string, handler: (event: R) => void, eventMerger?: IEventMerger<R, E>, minimumTimeMs?: number): IDisposable {
- - return new TimeoutThrottledDomListener<R, E>(node, type, handler, eventMerger, minimumTimeMs);
- +export function addDisposableThrottledListener<R, E extends Event = Event>(
- + node: any,
- + type: string,
- + handler: (event: R) => void,
- + eventMerger?: IEventMerger<R, E>,
- + minimumTimeMs?: number,
- +): IDisposable {
- + return new TimeoutThrottledDomListener<R, E>(node, type, handler, eventMerger, minimumTimeMs)
- }
-
- export function getComputedStyle(el: HTMLElement): CSSStyleDeclaration {
- - return getWindow(el).getComputedStyle(el, null);
- + return getWindow(el).getComputedStyle(el, null)
- }
-
- -export function getClientArea(element: HTMLElement, defaultValue?: Dimension, fallbackElement?: HTMLElement): Dimension {
- - const elWindow = getWindow(element);
- - const elDocument = elWindow.document;
- +export function getClientArea(
- + element: HTMLElement,
- + defaultValue?: Dimension,
- + fallbackElement?: HTMLElement,
- +): Dimension {
- + const elWindow = getWindow(element)
- + const elDocument = elWindow.document
-
- // Try with DOM clientWidth / clientHeight
- if (element !== elDocument.body) {
- - return new Dimension(element.clientWidth, element.clientHeight);
- + return new Dimension(element.clientWidth, element.clientHeight)
- }
-
- // 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
- if (platform.isIOS && elWindow?.visualViewport) {
- - return new Dimension(elWindow.visualViewport.width, elWindow.visualViewport.height);
- + return new Dimension(elWindow.visualViewport.width, elWindow.visualViewport.height)
- }
-
- // Try innerWidth / innerHeight
- if (elWindow?.innerWidth && elWindow.innerHeight) {
- - return new Dimension(elWindow.innerWidth, elWindow.innerHeight);
- + return new Dimension(elWindow.innerWidth, elWindow.innerHeight)
- }
-
- // Try with document.body.clientWidth / document.body.clientHeight
- if (elDocument.body && elDocument.body.clientWidth && elDocument.body.clientHeight) {
- - return new Dimension(elDocument.body.clientWidth, elDocument.body.clientHeight);
- + return new Dimension(elDocument.body.clientWidth, elDocument.body.clientHeight)
- }
-
- // Try with document.documentElement.clientWidth / document.documentElement.clientHeight
- - if (elDocument.documentElement && elDocument.documentElement.clientWidth && elDocument.documentElement.clientHeight) {
- - return new Dimension(elDocument.documentElement.clientWidth, elDocument.documentElement.clientHeight);
- + if (
- + elDocument.documentElement &&
- + elDocument.documentElement.clientWidth &&
- + elDocument.documentElement.clientHeight
- + ) {
- + return new Dimension(elDocument.documentElement.clientWidth, elDocument.documentElement.clientHeight)
- }
-
- if (fallbackElement) {
- - return getClientArea(fallbackElement, defaultValue);
- + return getClientArea(fallbackElement, defaultValue)
- }
-
- if (defaultValue) {
- - return defaultValue;
- + return defaultValue
- }
-
- - throw new Error('Unable to figure out browser width and height');
- + throw new Error("Unable to figure out browser width and height")
- }
-
- class SizeUtils {
- // Adapted from WinJS
- // Converts a CSS positioning string for the specified element to pixels.
- private static convertToPixels(element: HTMLElement, value: string): number {
- - return parseFloat(value) || 0;
- + return parseFloat(value) || 0
- }
-
- private static getDimension(element: HTMLElement, cssPropertyName: string): number {
- - const computedStyle = getComputedStyle(element);
- - const value = computedStyle ? computedStyle.getPropertyValue(cssPropertyName) : '0';
- - return SizeUtils.convertToPixels(element, value);
- + const computedStyle = getComputedStyle(element)
- + const value = computedStyle ? computedStyle.getPropertyValue(cssPropertyName) : "0"
- + return SizeUtils.convertToPixels(element, value)
- }
-
- static getBorderLeftWidth(element: HTMLElement): number {
- - return SizeUtils.getDimension(element, 'border-left-width');
- + return SizeUtils.getDimension(element, "border-left-width")
- }
- static getBorderRightWidth(element: HTMLElement): number {
- - return SizeUtils.getDimension(element, 'border-right-width');
- + return SizeUtils.getDimension(element, "border-right-width")
- }
- static getBorderTopWidth(element: HTMLElement): number {
- - return SizeUtils.getDimension(element, 'border-top-width');
- + return SizeUtils.getDimension(element, "border-top-width")
- }
- static getBorderBottomWidth(element: HTMLElement): number {
- - return SizeUtils.getDimension(element, 'border-bottom-width');
- + return SizeUtils.getDimension(element, "border-bottom-width")
- }
-
- static getPaddingLeft(element: HTMLElement): number {
- - return SizeUtils.getDimension(element, 'padding-left');
- + return SizeUtils.getDimension(element, "padding-left")
- }
- static getPaddingRight(element: HTMLElement): number {
- - return SizeUtils.getDimension(element, 'padding-right');
- + return SizeUtils.getDimension(element, "padding-right")
- }
- static getPaddingTop(element: HTMLElement): number {
- - return SizeUtils.getDimension(element, 'padding-top');
- + return SizeUtils.getDimension(element, "padding-top")
- }
- static getPaddingBottom(element: HTMLElement): number {
- - return SizeUtils.getDimension(element, 'padding-bottom');
- + return SizeUtils.getDimension(element, "padding-bottom")
- }
-
- static getMarginLeft(element: HTMLElement): number {
- - return SizeUtils.getDimension(element, 'margin-left');
- + return SizeUtils.getDimension(element, "margin-left")
- }
- static getMarginTop(element: HTMLElement): number {
- - return SizeUtils.getDimension(element, 'margin-top');
- + return SizeUtils.getDimension(element, "margin-top")
- }
- static getMarginRight(element: HTMLElement): number {
- - return SizeUtils.getDimension(element, 'margin-right');
- + return SizeUtils.getDimension(element, "margin-right")
- }
- static getMarginBottom(element: HTMLElement): number {
- - return SizeUtils.getDimension(element, 'margin-bottom');
- + return SizeUtils.getDimension(element, "margin-bottom")
- }
- }
-
- @@ -562,138 +662,148 @@ class SizeUtils {
- // Position & Dimension
-
- export interface IDimension {
- - readonly width: number;
- - readonly height: number;
- + readonly width: number
- + readonly height: number
- }
-
- export class Dimension implements IDimension {
- -
- - static readonly None = new Dimension(0, 0);
- + static readonly None = new Dimension(0, 0)
-
- constructor(
- readonly width: number,
- readonly height: number,
- - ) { }
- + ) {}
-
- with(width: number = this.width, height: number = this.height): Dimension {
- if (width !== this.width || height !== this.height) {
- - return new Dimension(width, height);
- + return new Dimension(width, height)
- } else {
- - return this;
- + return this
- }
- }
-
- static is(obj: unknown): obj is IDimension {
- - return typeof obj === 'object' && typeof (<IDimension>obj).height === 'number' && typeof (<IDimension>obj).width === 'number';
- + return (
- + typeof obj === "object" &&
- + typeof (<IDimension>obj).height === "number" &&
- + typeof (<IDimension>obj).width === "number"
- + )
- }
-
- static lift(obj: IDimension): Dimension {
- if (obj instanceof Dimension) {
- - return obj;
- + return obj
- } else {
- - return new Dimension(obj.width, obj.height);
- + return new Dimension(obj.width, obj.height)
- }
- }
-
- static equals(a: Dimension | undefined, b: Dimension | undefined): boolean {
- if (a === b) {
- - return true;
- + return true
- }
- if (!a || !b) {
- - return false;
- + return false
- }
- - return a.width === b.width && a.height === b.height;
- + return a.width === b.width && a.height === b.height
- }
- }
-
- export interface IDomPosition {
- - readonly left: number;
- - readonly top: number;
- + readonly left: number
- + readonly top: number
- }
-
- export function getTopLeftOffset(element: HTMLElement): IDomPosition {
- // Adapted from WinJS.Utilities.getPosition
- // and added borders to the mix
-
- - let offsetParent = element.offsetParent;
- - let top = element.offsetTop;
- - let left = element.offsetLeft;
- + let offsetParent = element.offsetParent
- + let top = element.offsetTop
- + let left = element.offsetLeft
-
- while (
- - (element = <HTMLElement>element.parentNode) !== null
- - && element !== element.ownerDocument.body
- - && element !== element.ownerDocument.documentElement
- + (element = <HTMLElement>element.parentNode) !== null &&
- + element !== element.ownerDocument.body &&
- + element !== element.ownerDocument.documentElement
- ) {
- - top -= element.scrollTop;
- - const c = isShadowRoot(element) ? null : getComputedStyle(element);
- + top -= element.scrollTop
- + const c = isShadowRoot(element) ? null : getComputedStyle(element)
- if (c) {
- - left -= c.direction !== 'rtl' ? element.scrollLeft : -element.scrollLeft;
- + left -= c.direction !== "rtl" ? element.scrollLeft : -element.scrollLeft
- }
-
- if (element === offsetParent) {
- - left += SizeUtils.getBorderLeftWidth(element);
- - top += SizeUtils.getBorderTopWidth(element);
- - top += element.offsetTop;
- - left += element.offsetLeft;
- - offsetParent = element.offsetParent;
- + left += SizeUtils.getBorderLeftWidth(element)
- + top += SizeUtils.getBorderTopWidth(element)
- + top += element.offsetTop
- + left += element.offsetLeft
- + offsetParent = element.offsetParent
- }
- }
-
- return {
- left: left,
- - top: top
- - };
- + top: top,
- + }
- }
-
- export interface IDomNodePagePosition {
- - left: number;
- - top: number;
- - width: number;
- - height: number;
- + left: number
- + top: number
- + width: number
- + height: number
- }
-
- export function size(element: HTMLElement, width: number | null, height: number | null): void {
- - if (typeof width === 'number') {
- - element.style.width = `${width}px`;
- + if (typeof width === "number") {
- + element.style.width = `${width}px`
- }
-
- - if (typeof height === 'number') {
- - element.style.height = `${height}px`;
- + if (typeof height === "number") {
- + element.style.height = `${height}px`
- }
- }
-
- -export function position(element: HTMLElement, top: number, right?: number, bottom?: number, left?: number, position: string = 'absolute'): void {
- - if (typeof top === 'number') {
- - element.style.top = `${top}px`;
- +export function position(
- + element: HTMLElement,
- + top: number,
- + right?: number,
- + bottom?: number,
- + left?: number,
- + position: string = "absolute",
- +): void {
- + if (typeof top === "number") {
- + element.style.top = `${top}px`
- }
-
- - if (typeof right === 'number') {
- - element.style.right = `${right}px`;
- + if (typeof right === "number") {
- + element.style.right = `${right}px`
- }
-
- - if (typeof bottom === 'number') {
- - element.style.bottom = `${bottom}px`;
- + if (typeof bottom === "number") {
- + element.style.bottom = `${bottom}px`
- }
-
- - if (typeof left === 'number') {
- - element.style.left = `${left}px`;
- + if (typeof left === "number") {
- + element.style.left = `${left}px`
- }
-
- - element.style.position = position;
- + element.style.position = position
- }
-
- /**
- * Returns the position of a dom node relative to the entire page.
- */
- export function getDomNodePagePosition(domNode: HTMLElement): IDomNodePagePosition {
- - const bb = domNode.getBoundingClientRect();
- - const window = getWindow(domNode);
- + const bb = domNode.getBoundingClientRect()
- + const window = getWindow(domNode)
- return {
- left: bb.left + window.scrollX,
- top: bb.top + window.scrollY,
- width: bb.width,
- - height: bb.height
- - };
- + height: bb.height,
- + }
- }
-
- /**
- @@ -704,105 +814,104 @@ export function getDomNodePagePosition(domNode: HTMLElement): IDomNodePagePositi
- * @returns true if the element is in the bottom right quarter of the container
- */
- export function isElementInBottomRightQuarter(element: HTMLElement, container: HTMLElement): boolean {
- - const position = getDomNodePagePosition(element);
- - const clientArea = getClientArea(container);
- + const position = getDomNodePagePosition(element)
- + const clientArea = getClientArea(container)
-
- - return position.left > clientArea.width / 2 && position.top > clientArea.height / 2;
- + return position.left > clientArea.width / 2 && position.top > clientArea.height / 2
- }
-
- /**
- * Returns the effective zoom on a given element before window zoom level is applied
- */
- export function getDomNodeZoomLevel(domNode: HTMLElement): number {
- - let testElement: HTMLElement | null = domNode;
- - let zoom = 1.0;
- + let testElement: HTMLElement | null = domNode
- + let zoom = 1.0
- do {
- - const elementZoomLevel = (getComputedStyle(testElement) as any).zoom;
- - if (elementZoomLevel !== null && elementZoomLevel !== undefined && elementZoomLevel !== '1') {
- - zoom *= elementZoomLevel;
- + const elementZoomLevel = (getComputedStyle(testElement) as any).zoom
- + if (elementZoomLevel !== null && elementZoomLevel !== undefined && elementZoomLevel !== "1") {
- + zoom *= elementZoomLevel
- }
-
- - testElement = testElement.parentElement;
- - } while (testElement !== null && testElement !== testElement.ownerDocument.documentElement);
- + testElement = testElement.parentElement
- + } while (testElement !== null && testElement !== testElement.ownerDocument.documentElement)
-
- - return zoom;
- + return zoom
- }
-
- -
- // Adapted from WinJS
- // Gets the width of the element, including margins.
- export function getTotalWidth(element: HTMLElement): number {
- - const margin = SizeUtils.getMarginLeft(element) + SizeUtils.getMarginRight(element);
- - return element.offsetWidth + margin;
- + const margin = SizeUtils.getMarginLeft(element) + SizeUtils.getMarginRight(element)
- + return element.offsetWidth + margin
- }
-
- export function getContentWidth(element: HTMLElement): number {
- - const border = SizeUtils.getBorderLeftWidth(element) + SizeUtils.getBorderRightWidth(element);
- - const padding = SizeUtils.getPaddingLeft(element) + SizeUtils.getPaddingRight(element);
- - return element.offsetWidth - border - padding;
- + const border = SizeUtils.getBorderLeftWidth(element) + SizeUtils.getBorderRightWidth(element)
- + const padding = SizeUtils.getPaddingLeft(element) + SizeUtils.getPaddingRight(element)
- + return element.offsetWidth - border - padding
- }
-
- export function getTotalScrollWidth(element: HTMLElement): number {
- - const margin = SizeUtils.getMarginLeft(element) + SizeUtils.getMarginRight(element);
- - return element.scrollWidth + margin;
- + const margin = SizeUtils.getMarginLeft(element) + SizeUtils.getMarginRight(element)
- + return element.scrollWidth + margin
- }
-
- // Adapted from WinJS
- // Gets the height of the content of the specified element. The content height does not include borders or padding.
- export function getContentHeight(element: HTMLElement): number {
- - const border = SizeUtils.getBorderTopWidth(element) + SizeUtils.getBorderBottomWidth(element);
- - const padding = SizeUtils.getPaddingTop(element) + SizeUtils.getPaddingBottom(element);
- - return element.offsetHeight - border - padding;
- + const border = SizeUtils.getBorderTopWidth(element) + SizeUtils.getBorderBottomWidth(element)
- + const padding = SizeUtils.getPaddingTop(element) + SizeUtils.getPaddingBottom(element)
- + return element.offsetHeight - border - padding
- }
-
- // Adapted from WinJS
- // Gets the height of the element, including its margins.
- export function getTotalHeight(element: HTMLElement): number {
- - const margin = SizeUtils.getMarginTop(element) + SizeUtils.getMarginBottom(element);
- - return element.offsetHeight + margin;
- + const margin = SizeUtils.getMarginTop(element) + SizeUtils.getMarginBottom(element)
- + return element.offsetHeight + margin
- }
-
- // Gets the left coordinate of the specified element relative to the specified parent.
- function getRelativeLeft(element: HTMLElement, parent: HTMLElement): number {
- if (element === null) {
- - return 0;
- + return 0
- }
-
- - const elementPosition = getTopLeftOffset(element);
- - const parentPosition = getTopLeftOffset(parent);
- - return elementPosition.left - parentPosition.left;
- + const elementPosition = getTopLeftOffset(element)
- + const parentPosition = getTopLeftOffset(parent)
- + return elementPosition.left - parentPosition.left
- }
-
- export function getLargestChildWidth(parent: HTMLElement, children: HTMLElement[]): number {
- const childWidths = children.map((child) => {
- - return Math.max(getTotalScrollWidth(child), getTotalWidth(child)) + getRelativeLeft(child, parent) || 0;
- - });
- - const maxWidth = Math.max(...childWidths);
- - return maxWidth;
- + return Math.max(getTotalScrollWidth(child), getTotalWidth(child)) + getRelativeLeft(child, parent) || 0
- + })
- + const maxWidth = Math.max(...childWidths)
- + return maxWidth
- }
-
- // ----------------------------------------------------------------------------------------
-
- export function isAncestor(testChild: Node | null, testAncestor: Node | null): boolean {
- - return Boolean(testAncestor?.contains(testChild));
- + return Boolean(testAncestor?.contains(testChild))
- }
-
- -const parentFlowToDataKey = 'parentFlowToElementId';
- +const parentFlowToDataKey = "parentFlowToElementId"
-
- /**
- * Set an explicit parent to use for nodes that are not part of the
- * regular dom structure.
- */
- export function setParentFlowTo(fromChildElement: HTMLElement, toParentElement: Element): void {
- - fromChildElement.dataset[parentFlowToDataKey] = toParentElement.id;
- + fromChildElement.dataset[parentFlowToDataKey] = toParentElement.id
- }
-
- function getParentFlowToElement(node: HTMLElement): HTMLElement | null {
- - const flowToParentId = node.dataset[parentFlowToDataKey];
- - if (typeof flowToParentId === 'string') {
- - return node.ownerDocument.getElementById(flowToParentId);
- + const flowToParentId = node.dataset[parentFlowToDataKey]
- + if (typeof flowToParentId === "string") {
- + return node.ownerDocument.getElementById(flowToParentId)
- }
- - return null;
- + return null
- }
-
- /**
- @@ -810,72 +919,78 @@ function getParentFlowToElement(node: HTMLElement): HTMLElement | null {
- * parents set by `setParentFlowTo`.
- */
- export function isAncestorUsingFlowTo(testChild: Node, testAncestor: Node): boolean {
- - let node: Node | null = testChild;
- + let node: Node | null = testChild
- while (node) {
- if (node === testAncestor) {
- - return true;
- + return true
- }
-
- if (isHTMLElement(node)) {
- - const flowToParentElement = getParentFlowToElement(node);
- + const flowToParentElement = getParentFlowToElement(node)
- if (flowToParentElement) {
- - node = flowToParentElement;
- - continue;
- + node = flowToParentElement
- + continue
- }
- }
- - node = node.parentNode;
- + node = node.parentNode
- }
-
- - return false;
- + return false
- }
-
- -export function findParentWithClass(node: HTMLElement, clazz: string, stopAtClazzOrNode?: string | HTMLElement): HTMLElement | null {
- +export function findParentWithClass(
- + node: HTMLElement,
- + clazz: string,
- + stopAtClazzOrNode?: string | HTMLElement,
- +): HTMLElement | null {
- while (node && node.nodeType === node.ELEMENT_NODE) {
- if (node.classList.contains(clazz)) {
- - return node;
- + return node
- }
-
- if (stopAtClazzOrNode) {
- - if (typeof stopAtClazzOrNode === 'string') {
- + if (typeof stopAtClazzOrNode === "string") {
- if (node.classList.contains(stopAtClazzOrNode)) {
- - return null;
- + return null
- }
- } else {
- if (node === stopAtClazzOrNode) {
- - return null;
- + return null
- }
- }
- }
-
- - node = <HTMLElement>node.parentNode;
- + node = <HTMLElement>node.parentNode
- }
-
- - return null;
- + return null
- }
-
- -export function hasParentWithClass(node: HTMLElement, clazz: string, stopAtClazzOrNode?: string | HTMLElement): boolean {
- - return !!findParentWithClass(node, clazz, stopAtClazzOrNode);
- +export function hasParentWithClass(
- + node: HTMLElement,
- + clazz: string,
- + stopAtClazzOrNode?: string | HTMLElement,
- +): boolean {
- + return !!findParentWithClass(node, clazz, stopAtClazzOrNode)
- }
-
- export function isShadowRoot(node: Node): node is ShadowRoot {
- - return (
- - node && !!(<ShadowRoot>node).host && !!(<ShadowRoot>node).mode
- - );
- + return node && !!(<ShadowRoot>node).host && !!(<ShadowRoot>node).mode
- }
-
- export function isInShadowDOM(domNode: Node): boolean {
- - return !!getShadowRoot(domNode);
- + return !!getShadowRoot(domNode)
- }
-
- export function getShadowRoot(domNode: Node): ShadowRoot | null {
- while (domNode.parentNode) {
- if (domNode === domNode.ownerDocument?.body) {
- // reached the body
- - return null;
- + return null
- }
- - domNode = domNode.parentNode;
- + domNode = domNode.parentNode
- }
- - return isShadowRoot(domNode) ? domNode : null;
- + return isShadowRoot(domNode) ? domNode : null
- }
-
- /**
- @@ -884,13 +999,13 @@ export function getShadowRoot(domNode: Node): ShadowRoot | null {
- * window if no window has focus.
- */
- export function getActiveElement(): Element | null {
- - let result = getActiveDocument().activeElement;
- + let result = getActiveDocument().activeElement
-
- while (result?.shadowRoot) {
- - result = result.shadowRoot.activeElement;
- + result = result.shadowRoot.activeElement
- }
-
- - return result;
- + return result
- }
-
- /**
- @@ -899,7 +1014,7 @@ export function getActiveElement(): Element | null {
- * window has focus.
- */
- export function isActiveElement(element: Element): boolean {
- - return getActiveElement() === element;
- + return getActiveElement() === element
- }
-
- /**
- @@ -907,7 +1022,7 @@ export function isActiveElement(element: Element): boolean {
- * `ancestor`. Falls back to the main window if no window has focus.
- */
- export function isAncestorOfActiveElement(ancestor: Element): boolean {
- - return isAncestor(getActiveElement(), ancestor);
- + return isAncestor(getActiveElement(), ancestor)
- }
-
- /**
- @@ -915,7 +1030,7 @@ export function isAncestorOfActiveElement(ancestor: Element): boolean {
- * document has focus or will be the main windows document.
- */
- export function isActiveDocument(element: Element): boolean {
- - return element.ownerDocument === getActiveDocument();
- + return element.ownerDocument === getActiveDocument()
- }
-
- /**
- @@ -925,11 +1040,11 @@ export function isActiveDocument(element: Element): boolean {
- */
- export function getActiveDocument(): Document {
- if (getWindowsCount() <= 1) {
- - return mainWindow.document;
- + return mainWindow.document
- }
-
- - const documents = Array.from(getWindows()).map(({ window }) => window.document);
- - return documents.find(doc => doc.hasFocus()) ?? mainWindow.document;
- + const documents = Array.from(getWindows()).map(({ window }) => window.document)
- + return documents.find((doc) => doc.hasFocus()) ?? mainWindow.document
- }
-
- /**
- @@ -938,313 +1053,316 @@ export function getActiveDocument(): Document {
- * the main window.
- */
- export function getActiveWindow(): CodeWindow {
- - const document = getActiveDocument();
- - return (document.defaultView?.window ?? mainWindow) as CodeWindow;
- + const document = getActiveDocument()
- + return (document.defaultView?.window ?? mainWindow) as CodeWindow
- }
-
- interface IMutationObserver {
- - users: number;
- - readonly observer: MutationObserver;
- - readonly onDidMutate: event.Event<MutationRecord[]>;
- + users: number
- + readonly observer: MutationObserver
- + readonly onDidMutate: event.Event<MutationRecord[]>
- }
-
- -export const sharedMutationObserver = new class {
- -
- - readonly mutationObservers = new Map<Node, Map<number, IMutationObserver>>();
- +export const sharedMutationObserver = new (class {
- + readonly mutationObservers = new Map<Node, Map<number, IMutationObserver>>()
-
- observe(target: Node, disposables: DisposableStore, options?: MutationObserverInit): event.Event<MutationRecord[]> {
- - let mutationObserversPerTarget = this.mutationObservers.get(target);
- + let mutationObserversPerTarget = this.mutationObservers.get(target)
- if (!mutationObserversPerTarget) {
- - mutationObserversPerTarget = new Map<number, IMutationObserver>();
- - this.mutationObservers.set(target, mutationObserversPerTarget);
- + mutationObserversPerTarget = new Map<number, IMutationObserver>()
- + this.mutationObservers.set(target, mutationObserversPerTarget)
- }
-
- - const optionsHash = hash(options);
- - let mutationObserverPerOptions = mutationObserversPerTarget.get(optionsHash);
- + const optionsHash = hash(options)
- + let mutationObserverPerOptions = mutationObserversPerTarget.get(optionsHash)
- if (!mutationObserverPerOptions) {
- - const onDidMutate = new event.Emitter<MutationRecord[]>();
- - const observer = new MutationObserver(mutations => onDidMutate.fire(mutations));
- - observer.observe(target, options);
- + const onDidMutate = new event.Emitter<MutationRecord[]>()
- + const observer = new MutationObserver((mutations) => onDidMutate.fire(mutations))
- + observer.observe(target, options)
-
- - const resolvedMutationObserverPerOptions = mutationObserverPerOptions = {
- + const resolvedMutationObserverPerOptions = (mutationObserverPerOptions = {
- users: 1,
- observer,
- - onDidMutate: onDidMutate.event
- - };
- + onDidMutate: onDidMutate.event,
- + })
-
- - disposables.add(toDisposable(() => {
- - resolvedMutationObserverPerOptions.users -= 1;
- + disposables.add(
- + toDisposable(() => {
- + resolvedMutationObserverPerOptions.users -= 1
-
- - if (resolvedMutationObserverPerOptions.users === 0) {
- - onDidMutate.dispose();
- - observer.disconnect();
- + if (resolvedMutationObserverPerOptions.users === 0) {
- + onDidMutate.dispose()
- + observer.disconnect()
-
- - mutationObserversPerTarget?.delete(optionsHash);
- - if (mutationObserversPerTarget?.size === 0) {
- - this.mutationObservers.delete(target);
- + mutationObserversPerTarget?.delete(optionsHash)
- + if (mutationObserversPerTarget?.size === 0) {
- + this.mutationObservers.delete(target)
- + }
- }
- - }
- - }));
- + }),
- + )
-
- - mutationObserversPerTarget.set(optionsHash, mutationObserverPerOptions);
- + mutationObserversPerTarget.set(optionsHash, mutationObserverPerOptions)
- } else {
- - mutationObserverPerOptions.users += 1;
- + mutationObserverPerOptions.users += 1
- }
-
- - return mutationObserverPerOptions.onDidMutate;
- + return mutationObserverPerOptions.onDidMutate
- }
- -};
- +})()
-
- export function createMetaElement(container: HTMLElement = mainWindow.document.head): HTMLMetaElement {
- - return createHeadElement('meta', container) as HTMLMetaElement;
- + return createHeadElement("meta", container) as HTMLMetaElement
- }
-
- export function createLinkElement(container: HTMLElement = mainWindow.document.head): HTMLLinkElement {
- - return createHeadElement('link', container) as HTMLLinkElement;
- + return createHeadElement("link", container) as HTMLLinkElement
- }
-
- function createHeadElement(tagName: string, container: HTMLElement = mainWindow.document.head): HTMLElement {
- - const element = document.createElement(tagName);
- - container.appendChild(element);
- - return element;
- + const element = document.createElement(tagName)
- + container.appendChild(element)
- + return element
- }
-
- export function isHTMLElement(e: unknown): e is HTMLElement {
- // eslint-disable-next-line no-restricted-syntax
- - return e instanceof HTMLElement || e instanceof getWindow(e as Node).HTMLElement;
- + return e instanceof HTMLElement || e instanceof getWindow(e as Node).HTMLElement
- }
-
- export function isHTMLAnchorElement(e: unknown): e is HTMLAnchorElement {
- // eslint-disable-next-line no-restricted-syntax
- - return e instanceof HTMLAnchorElement || e instanceof getWindow(e as Node).HTMLAnchorElement;
- + return e instanceof HTMLAnchorElement || e instanceof getWindow(e as Node).HTMLAnchorElement
- }
-
- export function isHTMLSpanElement(e: unknown): e is HTMLSpanElement {
- // eslint-disable-next-line no-restricted-syntax
- - return e instanceof HTMLSpanElement || e instanceof getWindow(e as Node).HTMLSpanElement;
- + return e instanceof HTMLSpanElement || e instanceof getWindow(e as Node).HTMLSpanElement
- }
-
- export function isHTMLTextAreaElement(e: unknown): e is HTMLTextAreaElement {
- // eslint-disable-next-line no-restricted-syntax
- - return e instanceof HTMLTextAreaElement || e instanceof getWindow(e as Node).HTMLTextAreaElement;
- + return e instanceof HTMLTextAreaElement || e instanceof getWindow(e as Node).HTMLTextAreaElement
- }
-
- export function isHTMLInputElement(e: unknown): e is HTMLInputElement {
- // eslint-disable-next-line no-restricted-syntax
- - return e instanceof HTMLInputElement || e instanceof getWindow(e as Node).HTMLInputElement;
- + return e instanceof HTMLInputElement || e instanceof getWindow(e as Node).HTMLInputElement
- }
-
- export function isHTMLButtonElement(e: unknown): e is HTMLButtonElement {
- // eslint-disable-next-line no-restricted-syntax
- - return e instanceof HTMLButtonElement || e instanceof getWindow(e as Node).HTMLButtonElement;
- + return e instanceof HTMLButtonElement || e instanceof getWindow(e as Node).HTMLButtonElement
- }
-
- export function isHTMLDivElement(e: unknown): e is HTMLDivElement {
- // eslint-disable-next-line no-restricted-syntax
- - return e instanceof HTMLDivElement || e instanceof getWindow(e as Node).HTMLDivElement;
- + return e instanceof HTMLDivElement || e instanceof getWindow(e as Node).HTMLDivElement
- }
-
- export function isSVGElement(e: unknown): e is SVGElement {
- // eslint-disable-next-line no-restricted-syntax
- - return e instanceof SVGElement || e instanceof getWindow(e as Node).SVGElement;
- + return e instanceof SVGElement || e instanceof getWindow(e as Node).SVGElement
- }
-
- export function isMouseEvent(e: unknown): e is MouseEvent {
- // eslint-disable-next-line no-restricted-syntax
- - return e instanceof MouseEvent || e instanceof getWindow(e as UIEvent).MouseEvent;
- + return e instanceof MouseEvent || e instanceof getWindow(e as UIEvent).MouseEvent
- }
-
- export function isKeyboardEvent(e: unknown): e is KeyboardEvent {
- // eslint-disable-next-line no-restricted-syntax
- - return e instanceof KeyboardEvent || e instanceof getWindow(e as UIEvent).KeyboardEvent;
- + return e instanceof KeyboardEvent || e instanceof getWindow(e as UIEvent).KeyboardEvent
- }
-
- export function isPointerEvent(e: unknown): e is PointerEvent {
- // eslint-disable-next-line no-restricted-syntax
- - return e instanceof PointerEvent || e instanceof getWindow(e as UIEvent).PointerEvent;
- + return e instanceof PointerEvent || e instanceof getWindow(e as UIEvent).PointerEvent
- }
-
- export function isDragEvent(e: unknown): e is DragEvent {
- // eslint-disable-next-line no-restricted-syntax
- - return e instanceof DragEvent || e instanceof getWindow(e as UIEvent).DragEvent;
- + return e instanceof DragEvent || e instanceof getWindow(e as UIEvent).DragEvent
- }
-
- export const EventType = {
- // Mouse
- - CLICK: 'click',
- - AUXCLICK: 'auxclick',
- - DBLCLICK: 'dblclick',
- - MOUSE_UP: 'mouseup',
- - MOUSE_DOWN: 'mousedown',
- - MOUSE_OVER: 'mouseover',
- - MOUSE_MOVE: 'mousemove',
- - MOUSE_OUT: 'mouseout',
- - MOUSE_ENTER: 'mouseenter',
- - MOUSE_LEAVE: 'mouseleave',
- - MOUSE_WHEEL: 'wheel',
- - POINTER_UP: 'pointerup',
- - POINTER_DOWN: 'pointerdown',
- - POINTER_MOVE: 'pointermove',
- - POINTER_LEAVE: 'pointerleave',
- - CONTEXT_MENU: 'contextmenu',
- - WHEEL: 'wheel',
- + CLICK: "click",
- + AUXCLICK: "auxclick",
- + DBLCLICK: "dblclick",
- + MOUSE_UP: "mouseup",
- + MOUSE_DOWN: "mousedown",
- + MOUSE_OVER: "mouseover",
- + MOUSE_MOVE: "mousemove",
- + MOUSE_OUT: "mouseout",
- + MOUSE_ENTER: "mouseenter",
- + MOUSE_LEAVE: "mouseleave",
- + MOUSE_WHEEL: "wheel",
- + POINTER_UP: "pointerup",
- + POINTER_DOWN: "pointerdown",
- + POINTER_MOVE: "pointermove",
- + POINTER_LEAVE: "pointerleave",
- + CONTEXT_MENU: "contextmenu",
- + WHEEL: "wheel",
- // Keyboard
- - KEY_DOWN: 'keydown',
- - KEY_PRESS: 'keypress',
- - KEY_UP: 'keyup',
- + KEY_DOWN: "keydown",
- + KEY_PRESS: "keypress",
- + KEY_UP: "keyup",
- // HTML Document
- - LOAD: 'load',
- - BEFORE_UNLOAD: 'beforeunload',
- - UNLOAD: 'unload',
- - PAGE_SHOW: 'pageshow',
- - PAGE_HIDE: 'pagehide',
- - PASTE: 'paste',
- - ABORT: 'abort',
- - ERROR: 'error',
- - RESIZE: 'resize',
- - SCROLL: 'scroll',
- - FULLSCREEN_CHANGE: 'fullscreenchange',
- - WK_FULLSCREEN_CHANGE: 'webkitfullscreenchange',
- + LOAD: "load",
- + BEFORE_UNLOAD: "beforeunload",
- + UNLOAD: "unload",
- + PAGE_SHOW: "pageshow",
- + PAGE_HIDE: "pagehide",
- + PASTE: "paste",
- + ABORT: "abort",
- + ERROR: "error",
- + RESIZE: "resize",
- + SCROLL: "scroll",
- + FULLSCREEN_CHANGE: "fullscreenchange",
- + WK_FULLSCREEN_CHANGE: "webkitfullscreenchange",
- // Form
- - SELECT: 'select',
- - CHANGE: 'change',
- - SUBMIT: 'submit',
- - RESET: 'reset',
- - FOCUS: 'focus',
- - FOCUS_IN: 'focusin',
- - FOCUS_OUT: 'focusout',
- - BLUR: 'blur',
- - INPUT: 'input',
- + SELECT: "select",
- + CHANGE: "change",
- + SUBMIT: "submit",
- + RESET: "reset",
- + FOCUS: "focus",
- + FOCUS_IN: "focusin",
- + FOCUS_OUT: "focusout",
- + BLUR: "blur",
- + INPUT: "input",
- // Local Storage
- - STORAGE: 'storage',
- + STORAGE: "storage",
- // Drag
- - DRAG_START: 'dragstart',
- - DRAG: 'drag',
- - DRAG_ENTER: 'dragenter',
- - DRAG_LEAVE: 'dragleave',
- - DRAG_OVER: 'dragover',
- - DROP: 'drop',
- - DRAG_END: 'dragend',
- + DRAG_START: "dragstart",
- + DRAG: "drag",
- + DRAG_ENTER: "dragenter",
- + DRAG_LEAVE: "dragleave",
- + DRAG_OVER: "dragover",
- + DROP: "drop",
- + DRAG_END: "dragend",
- // Animation
- - ANIMATION_START: browser.isWebKit ? 'webkitAnimationStart' : 'animationstart',
- - ANIMATION_END: browser.isWebKit ? 'webkitAnimationEnd' : 'animationend',
- - ANIMATION_ITERATION: browser.isWebKit ? 'webkitAnimationIteration' : 'animationiteration'
- -} as const;
- + ANIMATION_START: browser.isWebKit ? "webkitAnimationStart" : "animationstart",
- + ANIMATION_END: browser.isWebKit ? "webkitAnimationEnd" : "animationend",
- + ANIMATION_ITERATION: browser.isWebKit ? "webkitAnimationIteration" : "animationiteration",
- +} as const
-
- export interface EventLike {
- - preventDefault(): void;
- - stopPropagation(): void;
- + preventDefault(): void
- + stopPropagation(): void
- }
-
- export function isEventLike(obj: unknown): obj is EventLike {
- - const candidate = obj as EventLike | undefined;
- + const candidate = obj as EventLike | undefined
-
- - return !!(candidate && typeof candidate.preventDefault === 'function' && typeof candidate.stopPropagation === 'function');
- + return !!(
- + candidate &&
- + typeof candidate.preventDefault === "function" &&
- + typeof candidate.stopPropagation === "function"
- + )
- }
-
- export const EventHelper = {
- stop: <T extends EventLike>(e: T, cancelBubble?: boolean): T => {
- - e.preventDefault();
- + e.preventDefault()
- if (cancelBubble) {
- - e.stopPropagation();
- + e.stopPropagation()
- }
- - return e;
- - }
- -};
- + return e
- + },
- +}
-
- export interface IFocusTracker extends Disposable {
- - readonly onDidFocus: event.Event<void>;
- - readonly onDidBlur: event.Event<void>;
- - refreshState(): void;
- + readonly onDidFocus: event.Event<void>
- + readonly onDidBlur: event.Event<void>
- + refreshState(): void
- }
-
- export function saveParentsScrollTop(node: Element): number[] {
- - const r: number[] = [];
- + const r: number[] = []
- for (let i = 0; node && node.nodeType === node.ELEMENT_NODE; i++) {
- - r[i] = node.scrollTop;
- - node = <Element>node.parentNode;
- + r[i] = node.scrollTop
- + node = <Element>node.parentNode
- }
- - return r;
- + return r
- }
-
- export function restoreParentsScrollTop(node: Element, state: number[]): void {
- for (let i = 0; node && node.nodeType === node.ELEMENT_NODE; i++) {
- if (node.scrollTop !== state[i]) {
- - node.scrollTop = state[i];
- + node.scrollTop = state[i]
- }
- - node = <Element>node.parentNode;
- + node = <Element>node.parentNode
- }
- }
-
- class FocusTracker extends Disposable implements IFocusTracker {
- + private readonly _onDidFocus = this._register(new event.Emitter<void>())
- + readonly onDidFocus = this._onDidFocus.event
-
- - private readonly _onDidFocus = this._register(new event.Emitter<void>());
- - readonly onDidFocus = this._onDidFocus.event;
- + private readonly _onDidBlur = this._register(new event.Emitter<void>())
- + readonly onDidBlur = this._onDidBlur.event
-
- - private readonly _onDidBlur = this._register(new event.Emitter<void>());
- - readonly onDidBlur = this._onDidBlur.event;
- -
- - private _refreshStateHandler: () => void;
- + private _refreshStateHandler: () => void
-
- private static hasFocusWithin(element: HTMLElement | Window): boolean {
- if (isHTMLElement(element)) {
- - const shadowRoot = getShadowRoot(element);
- - const activeElement = (shadowRoot ? shadowRoot.activeElement : element.ownerDocument.activeElement);
- - return isAncestor(activeElement, element);
- + const shadowRoot = getShadowRoot(element)
- + const activeElement = shadowRoot ? shadowRoot.activeElement : element.ownerDocument.activeElement
- + return isAncestor(activeElement, element)
- } else {
- - const window = element;
- - return isAncestor(window.document.activeElement, window.document);
- + const window = element
- + return isAncestor(window.document.activeElement, window.document)
- }
- }
-
- constructor(element: HTMLElement | Window) {
- - super();
- - let hasFocus = FocusTracker.hasFocusWithin(element);
- - let loosingFocus = false;
- + super()
- + let hasFocus = FocusTracker.hasFocusWithin(element)
- + let loosingFocus = false
-
- const onFocus = () => {
- - loosingFocus = false;
- + loosingFocus = false
- if (!hasFocus) {
- - hasFocus = true;
- - this._onDidFocus.fire();
- + hasFocus = true
- + this._onDidFocus.fire()
- }
- - };
- + }
-
- const onBlur = () => {
- if (hasFocus) {
- - loosingFocus = true;
- - (isHTMLElement(element) ? getWindow(element) : element).setTimeout(() => {
- + loosingFocus = true
- + ;(isHTMLElement(element) ? getWindow(element) : element).setTimeout(() => {
- if (loosingFocus) {
- - loosingFocus = false;
- - hasFocus = false;
- - this._onDidBlur.fire();
- + loosingFocus = false
- + hasFocus = false
- + this._onDidBlur.fire()
- }
- - }, 0);
- + }, 0)
- }
- - };
- + }
-
- this._refreshStateHandler = () => {
- - const currentNodeHasFocus = FocusTracker.hasFocusWithin(<HTMLElement>element);
- + const currentNodeHasFocus = FocusTracker.hasFocusWithin(<HTMLElement>element)
- if (currentNodeHasFocus !== hasFocus) {
- if (hasFocus) {
- - onBlur();
- + onBlur()
- } else {
- - onFocus();
- + onFocus()
- }
- }
- - };
- + }
-
- - this._register(addDisposableListener(element, EventType.FOCUS, onFocus, true));
- - this._register(addDisposableListener(element, EventType.BLUR, onBlur, true));
- + this._register(addDisposableListener(element, EventType.FOCUS, onFocus, true))
- + this._register(addDisposableListener(element, EventType.BLUR, onBlur, true))
- if (isHTMLElement(element)) {
- - this._register(addDisposableListener(element, EventType.FOCUS_IN, () => this._refreshStateHandler()));
- - this._register(addDisposableListener(element, EventType.FOCUS_OUT, () => this._refreshStateHandler()));
- + this._register(addDisposableListener(element, EventType.FOCUS_IN, () => this._refreshStateHandler()))
- + this._register(addDisposableListener(element, EventType.FOCUS_OUT, () => this._refreshStateHandler()))
- }
- -
- }
-
- refreshState() {
- - this._refreshStateHandler();
- + this._refreshStateHandler()
- }
- }
-
- @@ -1255,153 +1373,165 @@ class FocusTracker extends Disposable implements IFocusTracker {
- * @returns An `IFocusTracker` instance.
- */
- export function trackFocus(element: HTMLElement | Window): IFocusTracker {
- - return new FocusTracker(element);
- + return new FocusTracker(element)
- }
-
- export function after<T extends Node>(sibling: HTMLElement, child: T): T {
- - sibling.after(child);
- - return child;
- + sibling.after(child)
- + return child
- }
-
- -export function append<T extends Node>(parent: HTMLElement, child: T): T;
- -export function append<T extends Node>(parent: HTMLElement, ...children: (T | string)[]): void;
- +export function append<T extends Node>(parent: HTMLElement, child: T): T
- +export function append<T extends Node>(parent: HTMLElement, ...children: (T | string)[]): void
- export function append<T extends Node>(parent: HTMLElement, ...children: (T | string)[]): T | void {
- - parent.append(...children);
- - if (children.length === 1 && typeof children[0] !== 'string') {
- - return <T>children[0];
- + parent.append(...children)
- + if (children.length === 1 && typeof children[0] !== "string") {
- + return <T>children[0]
- }
- }
-
- export function prepend<T extends Node>(parent: HTMLElement, child: T): T {
- - parent.insertBefore(child, parent.firstChild);
- - return child;
- + parent.insertBefore(child, parent.firstChild)
- + return child
- }
-
- /**
- * Removes all children from `parent` and appends `children`
- */
- export function reset(parent: HTMLElement, ...children: Array<Node | string>): void {
- - parent.innerText = '';
- - append(parent, ...children);
- + parent.innerText = ""
- + append(parent, ...children)
- }
-
- -const SELECTOR_REGEX = /([\w\-]+)?(#([\w\-]+))?((\.([\w\-]+))*)/;
- +const SELECTOR_REGEX = /([\w\-]+)?(#([\w\-]+))?((\.([\w\-]+))*)/
-
- export enum Namespace {
- - HTML = 'http://www.w3.org/1999/xhtml',
- - SVG = 'http://www.w3.org/2000/svg'
- + HTML = "http://www.w3.org/1999/xhtml",
- + SVG = "http://www.w3.org/2000/svg",
- }
-
- -function _$<T extends Element>(namespace: Namespace, description: string, attrs?: { [key: string]: any }, ...children: Array<Node | string>): T {
- - const match = SELECTOR_REGEX.exec(description);
- +function _$<T extends Element>(
- + namespace: Namespace,
- + description: string,
- + attrs?: { [key: string]: any },
- + ...children: Array<Node | string>
- +): T {
- + const match = SELECTOR_REGEX.exec(description)
-
- if (!match) {
- - throw new Error('Bad use of emmet');
- + throw new Error("Bad use of emmet")
- }
-
- - const tagName = match[1] || 'div';
- - let result: T;
- + const tagName = match[1] || "div"
- + let result: T
-
- if (namespace !== Namespace.HTML) {
- - result = document.createElementNS(namespace as string, tagName) as T;
- + result = document.createElementNS(namespace as string, tagName) as T
- } else {
- - result = document.createElement(tagName) as unknown as T;
- + result = document.createElement(tagName) as unknown as T
- }
-
- if (match[3]) {
- - result.id = match[3];
- + result.id = match[3]
- }
- if (match[4]) {
- - result.className = match[4].replace(/\./g, ' ').trim();
- + result.className = match[4].replace(/\./g, " ").trim()
- }
-
- if (attrs) {
- Object.entries(attrs).forEach(([name, value]) => {
- - if (typeof value === 'undefined') {
- - return;
- + if (typeof value === "undefined") {
- + return
- }
-
- if (/^on\w+$/.test(name)) {
- - (<any>result)[name] = value;
- - } else if (name === 'selected') {
- + ;(<any>result)[name] = value
- + } else if (name === "selected") {
- if (value) {
- - result.setAttribute(name, 'true');
- + result.setAttribute(name, "true")
- }
- -
- } else {
- - result.setAttribute(name, value);
- + result.setAttribute(name, value)
- }
- - });
- + })
- }
-
- - result.append(...children);
- + result.append(...children)
-
- - return result as T;
- + return result as T
- }
-
- -export function $<T extends HTMLElement>(description: string, attrs?: { [key: string]: any }, ...children: Array<Node | string>): T {
- - return _$(Namespace.HTML, description, attrs, ...children);
- +export function $<T extends HTMLElement>(
- + description: string,
- + attrs?: { [key: string]: any },
- + ...children: Array<Node | string>
- +): T {
- + return _$(Namespace.HTML, description, attrs, ...children)
- }
-
- -$.SVG = function <T extends SVGElement>(description: string, attrs?: { [key: string]: any }, ...children: Array<Node | string>): T {
- - return _$(Namespace.SVG, description, attrs, ...children);
- -};
- +$.SVG = function <T extends SVGElement>(
- + description: string,
- + attrs?: { [key: string]: any },
- + ...children: Array<Node | string>
- +): T {
- + return _$(Namespace.SVG, description, attrs, ...children)
- +}
-
- export function join(nodes: Node[], separator: Node | string): Node[] {
- - const result: Node[] = [];
- + const result: Node[] = []
-
- nodes.forEach((node, index) => {
- if (index > 0) {
- if (separator instanceof Node) {
- - result.push(separator.cloneNode());
- + result.push(separator.cloneNode())
- } else {
- - result.push(document.createTextNode(separator));
- + result.push(document.createTextNode(separator))
- }
- }
-
- - result.push(node);
- - });
- + result.push(node)
- + })
-
- - return result;
- + return result
- }
-
- export function setVisibility(visible: boolean, ...elements: HTMLElement[]): void {
- if (visible) {
- - show(...elements);
- + show(...elements)
- } else {
- - hide(...elements);
- + hide(...elements)
- }
- }
-
- export function show(...elements: HTMLElement[]): void {
- for (const element of elements) {
- - element.style.display = '';
- - element.removeAttribute('aria-hidden');
- + element.style.display = ""
- + element.removeAttribute("aria-hidden")
- }
- }
-
- export function hide(...elements: HTMLElement[]): void {
- for (const element of elements) {
- - element.style.display = 'none';
- - element.setAttribute('aria-hidden', 'true');
- + element.style.display = "none"
- + element.setAttribute("aria-hidden", "true")
- }
- }
-
- function findParentWithAttribute(node: Node | null, attribute: string): HTMLElement | null {
- while (node && node.nodeType === node.ELEMENT_NODE) {
- if (isHTMLElement(node) && node.hasAttribute(attribute)) {
- - return node;
- + return node
- }
-
- - node = node.parentNode;
- + node = node.parentNode
- }
-
- - return null;
- + return null
- }
-
- export function removeTabIndexAndUpdateFocus(node: HTMLElement): void {
- - if (!node || !node.hasAttribute('tabIndex')) {
- - return;
- + if (!node || !node.hasAttribute("tabIndex")) {
- + return
- }
-
- // If we are the currently focused element and tabIndex is removed,
- @@ -1409,35 +1539,35 @@ export function removeTabIndexAndUpdateFocus(node: HTMLElement): void {
- // typically never want that, rather put focus to the closest element
- // in the hierarchy of the parent DOM nodes.
- if (node.ownerDocument.activeElement === node) {
- - const parentFocusable = findParentWithAttribute(node.parentElement, 'tabIndex');
- - parentFocusable?.focus();
- + const parentFocusable = findParentWithAttribute(node.parentElement, "tabIndex")
- + parentFocusable?.focus()
- }
-
- - node.removeAttribute('tabindex');
- + node.removeAttribute("tabindex")
- }
-
- export function finalHandler<T extends Event>(fn: (event: T) => unknown): (event: T) => unknown {
- - return e => {
- - e.preventDefault();
- - e.stopPropagation();
- - fn(e);
- - };
- + return (e) => {
- + e.preventDefault()
- + e.stopPropagation()
- + fn(e)
- + }
- }
-
- export function domContentLoaded(targetWindow: Window): Promise<void> {
- - return new Promise<void>(resolve => {
- - const readyState = targetWindow.document.readyState;
- - if (readyState === 'complete' || (targetWindow.document && targetWindow.document.body !== null)) {
- - resolve(undefined);
- + return new Promise<void>((resolve) => {
- + const readyState = targetWindow.document.readyState
- + if (readyState === "complete" || (targetWindow.document && targetWindow.document.body !== null)) {
- + resolve(undefined)
- } else {
- const listener = () => {
- - targetWindow.window.removeEventListener('DOMContentLoaded', listener, false);
- - resolve();
- - };
- + targetWindow.window.removeEventListener("DOMContentLoaded", listener, false)
- + resolve()
- + }
-
- - targetWindow.window.addEventListener('DOMContentLoaded', listener, false);
- + targetWindow.window.addEventListener("DOMContentLoaded", listener, false)
- }
- - });
- + })
- }
-
- /**
- @@ -1449,8 +1579,8 @@ export function domContentLoaded(targetWindow: Window): Promise<void> {
- * with the screen pixels, it will sometimes be rendered with 2 screen pixels, and sometimes with 3 screen pixels.
- */
- export function computeScreenAwareSize(window: Window, cssPx: number): number {
- - const screenPx = window.devicePixelRatio * cssPx;
- - return Math.max(1, Math.floor(screenPx)) / window.devicePixelRatio;
- + const screenPx = window.devicePixelRatio * cssPx
- + return Math.max(1, Math.floor(screenPx)) / window.devicePixelRatio
- }
-
- /**
- @@ -1471,7 +1601,7 @@ export function windowOpenNoOpener(url: string): void {
- // See https://developer.mozilla.org/en-US/docs/Web/API/Window/open#noopener
- // However, this also doesn't allow us to realize if the browser blocked
- // the creation of the window.
- - mainWindow.open(url, '_blank', 'noopener');
- + mainWindow.open(url, "_blank", "noopener")
- }
-
- /**
- @@ -1485,15 +1615,12 @@ export function windowOpenNoOpener(url: string): void {
- *
- * In otherwords, you should almost always use {@link windowOpenNoOpener} instead of this function.
- */
- -const popupWidth = 780, popupHeight = 640;
- +const popupWidth = 780,
- + popupHeight = 640
- export function windowOpenPopup(url: string): void {
- - const left = Math.floor(mainWindow.screenLeft + mainWindow.innerWidth / 2 - popupWidth / 2);
- - const top = Math.floor(mainWindow.screenTop + mainWindow.innerHeight / 2 - popupHeight / 2);
- - mainWindow.open(
- - url,
- - '_blank',
- - `width=${popupWidth},height=${popupHeight},top=${top},left=${left}`
- - );
- + const left = Math.floor(mainWindow.screenLeft + mainWindow.innerWidth / 2 - popupWidth / 2)
- + const top = Math.floor(mainWindow.screenTop + mainWindow.innerHeight / 2 - popupHeight / 2)
- + mainWindow.open(url, "_blank", `width=${popupWidth},height=${popupHeight},top=${top},left=${left}`)
- }
-
- /**
- @@ -1512,86 +1639,83 @@ export function windowOpenPopup(url: string): void {
- * @returns boolean indicating if the {@link window.open} call succeeded
- */
- export function windowOpenWithSuccess(url: string, noOpener = true): boolean {
- - const newTab = mainWindow.open();
- + const newTab = mainWindow.open()
- if (newTab) {
- if (noOpener) {
- // see `windowOpenNoOpener` for details on why this is important
- - (newTab as any).opener = null;
- + ;(newTab as any).opener = null
- }
- - newTab.location.href = url;
- - return true;
- + newTab.location.href = url
- + return true
- }
- - return false;
- + return false
- }
-
- export function animate(targetWindow: Window, fn: () => void): IDisposable {
- const step = () => {
- - fn();
- - stepDisposable = scheduleAtNextAnimationFrame(targetWindow, step);
- - };
- + fn()
- + stepDisposable = scheduleAtNextAnimationFrame(targetWindow, step)
- + }
-
- - let stepDisposable = scheduleAtNextAnimationFrame(targetWindow, step);
- - return toDisposable(() => stepDisposable.dispose());
- + let stepDisposable = scheduleAtNextAnimationFrame(targetWindow, step)
- + return toDisposable(() => stepDisposable.dispose())
- }
-
- -RemoteAuthorities.setPreferredWebSchema(/^https:/.test(mainWindow.location.href) ? 'https' : 'http');
- +RemoteAuthorities.setPreferredWebSchema(/^https:/.test(mainWindow.location.href) ? "https" : "http")
-
- export function triggerDownload(dataOrUri: Uint8Array | URI, name: string): void {
- -
- // If the data is provided as Buffer, we create a
- // blob URL out of it to produce a valid link
- - let url: string;
- + let url: string
- if (URI.isUri(dataOrUri)) {
- - url = dataOrUri.toString(true);
- + url = dataOrUri.toString(true)
- } else {
- - const blob = new Blob([dataOrUri]);
- - url = URL.createObjectURL(blob);
- + const blob = new Blob([dataOrUri as Uint8Array<ArrayBuffer>])
- + url = URL.createObjectURL(blob)
-
- // Ensure to free the data from DOM eventually
- - setTimeout(() => URL.revokeObjectURL(url));
- + setTimeout(() => URL.revokeObjectURL(url))
- }
-
- // In order to download from the browser, the only way seems
- // to be creating a <a> element with download attribute that
- // points to the file to download.
- // See also https://developers.google.com/web/updates/2011/08/Downloading-resources-in-HTML5-a-download
- - const activeWindow = getActiveWindow();
- - const anchor = document.createElement('a');
- - activeWindow.document.body.appendChild(anchor);
- - anchor.download = name;
- - anchor.href = url;
- - anchor.click();
- + const activeWindow = getActiveWindow()
- + const anchor = document.createElement("a")
- + activeWindow.document.body.appendChild(anchor)
- + anchor.download = name
- + anchor.href = url
- + anchor.click()
-
- // Ensure to remove the element from DOM eventually
- - setTimeout(() => anchor.remove());
- + setTimeout(() => anchor.remove())
- }
-
- export function triggerUpload(): Promise<FileList | undefined> {
- - return new Promise<FileList | undefined>(resolve => {
- -
- + return new Promise<FileList | undefined>((resolve) => {
- // In order to upload to the browser, create a
- // input element of type `file` and click it
- // to gather the selected files
- - const activeWindow = getActiveWindow();
- - const input = document.createElement('input');
- - activeWindow.document.body.appendChild(input);
- - input.type = 'file';
- - input.multiple = true;
- + const activeWindow = getActiveWindow()
- + const input = document.createElement("input")
- + activeWindow.document.body.appendChild(input)
- + input.type = "file"
- + input.multiple = true
-
- // Resolve once the input event has fired once
- - event.Event.once(event.Event.fromDOMEventEmitter(input, 'input'))(() => {
- - resolve(input.files ?? undefined);
- - });
- + event.Event.once(event.Event.fromDOMEventEmitter(input, "input"))(() => {
- + resolve(input.files ?? undefined)
- + })
-
- - input.click();
- + input.click()
-
- // Ensure to remove the element from DOM eventually
- - setTimeout(() => input.remove());
- - });
- + setTimeout(() => input.remove())
- + })
- }
-
- export enum DetectedFullscreenMode {
- -
- /**
- * The document is fullscreen, e.g. because an element
- * in the document requested to be fullscreen.
- @@ -1602,28 +1726,30 @@ export enum DetectedFullscreenMode {
- * The browser is fullscreen, e.g. because the user enabled
- * native window fullscreen for it.
- */
- - BROWSER
- + BROWSER,
- }
-
- export interface IDetectedFullscreen {
- -
- /**
- * Figure out if the document is fullscreen or the browser.
- */
- - mode: DetectedFullscreenMode;
- + mode: DetectedFullscreenMode
-
- /**
- * Whether we know for sure that we are in fullscreen mode or
- * it is a guess.
- */
- - guess: boolean;
- + guess: boolean
- }
-
- export function detectFullscreen(targetWindow: Window): IDetectedFullscreen | null {
- -
- // Browser fullscreen: use DOM APIs to detect
- - if (targetWindow.document.fullscreenElement || (<any>targetWindow.document).webkitFullscreenElement || (<any>targetWindow.document).webkitIsFullScreen) {
- - return { mode: DetectedFullscreenMode.DOCUMENT, guess: false };
- + if (
- + targetWindow.document.fullscreenElement ||
- + (<any>targetWindow.document).webkitFullscreenElement ||
- + (<any>targetWindow.document).webkitIsFullScreen
- + ) {
- + return { mode: DetectedFullscreenMode.DOCUMENT, guess: false }
- }
-
- // There is no standard way to figure out if the browser
- @@ -1635,22 +1761,25 @@ export function detectFullscreen(targetWindow: Window): IDetectedFullscreen | nu
- // if the height of the window matches the screen height, we can
- // safely assume that the browser is fullscreen because no browser
- // chrome is taking height away (e.g. like toolbars).
- - return { mode: DetectedFullscreenMode.BROWSER, guess: false };
- + return { mode: DetectedFullscreenMode.BROWSER, guess: false }
- }
-
- if (platform.isMacintosh || platform.isLinux) {
- // macOS and Linux do not properly report `innerHeight`, only Windows does
- - if (targetWindow.outerHeight === targetWindow.screen.height && targetWindow.outerWidth === targetWindow.screen.width) {
- + if (
- + targetWindow.outerHeight === targetWindow.screen.height &&
- + targetWindow.outerWidth === targetWindow.screen.width
- + ) {
- // if the height of the browser matches the screen height, we can
- // only guess that we are in fullscreen. It is also possible that
- // the user has turned off taskbars in the OS and the browser is
- // simply able to span the entire size of the screen.
- - return { mode: DetectedFullscreenMode.BROWSER, guess: true };
- + return { mode: DetectedFullscreenMode.BROWSER, guess: true }
- }
- }
-
- // Not in fullscreen
- - return null;
- + return null
- }
-
- // -- sanitize and trusted html
- @@ -1659,136 +1788,184 @@ export function detectFullscreen(targetWindow: Window): IDetectedFullscreen | nu
- * Hooks dompurify using `afterSanitizeAttributes` to check that all `href` and `src`
- * attributes are valid.
- */
- -export function hookDomPurifyHrefAndSrcSanitizer(allowedProtocols: readonly string[], allowDataImages = false): IDisposable {
- +export function hookDomPurifyHrefAndSrcSanitizer(
- + allowedProtocols: readonly string[],
- + allowDataImages = false,
- +): IDisposable {
- // https://github.com/cure53/DOMPurify/blob/main/demos/hooks-scheme-allowlist.html
-
- // build an anchor to map URLs to
- - const anchor = document.createElement('a');
- + const anchor = document.createElement("a")
-
- - dompurify.addHook('afterSanitizeAttributes', (node) => {
- + dompurify.addHook("afterSanitizeAttributes", (node) => {
- // check all href/src attributes for validity
- - for (const attr of ['href', 'src']) {
- + for (const attr of ["href", "src"]) {
- if (node.hasAttribute(attr)) {
- - const attrValue = node.getAttribute(attr) as string;
- - if (attr === 'href' && attrValue.startsWith('#')) {
- + const attrValue = node.getAttribute(attr) as string
- + if (attr === "href" && attrValue.startsWith("#")) {
- // Allow fragment links
- - continue;
- + continue
- }
-
- - anchor.href = attrValue;
- - if (!allowedProtocols.includes(anchor.protocol.replace(/:$/, ''))) {
- - if (allowDataImages && attr === 'src' && anchor.href.startsWith('data:')) {
- - continue;
- + anchor.href = attrValue
- + if (!allowedProtocols.includes(anchor.protocol.replace(/:$/, ""))) {
- + if (allowDataImages && attr === "src" && anchor.href.startsWith("data:")) {
- + continue
- }
-
- - node.removeAttribute(attr);
- + node.removeAttribute(attr)
- }
- }
- }
- - });
- + })
-
- return toDisposable(() => {
- - dompurify.removeHook('afterSanitizeAttributes');
- - });
- + dompurify.removeHook("afterSanitizeAttributes")
- + })
- }
-
- -const defaultSafeProtocols = [
- - Schemas.http,
- - Schemas.https,
- - Schemas.command,
- -];
- +const defaultSafeProtocols = [Schemas.http, Schemas.https, Schemas.command]
-
- /**
- * List of safe, non-input html tags.
- */
- export const basicMarkupHtmlTags = Object.freeze([
- - 'a',
- - 'abbr',
- - 'b',
- - 'bdo',
- - 'blockquote',
- - 'br',
- - 'caption',
- - 'cite',
- - 'code',
- - 'col',
- - 'colgroup',
- - 'dd',
- - 'del',
- - 'details',
- - 'dfn',
- - 'div',
- - 'dl',
- - 'dt',
- - 'em',
- - 'figcaption',
- - 'figure',
- - 'h1',
- - 'h2',
- - 'h3',
- - 'h4',
- - 'h5',
- - 'h6',
- - 'hr',
- - 'i',
- - 'img',
- - 'input',
- - 'ins',
- - 'kbd',
- - 'label',
- - 'li',
- - 'mark',
- - 'ol',
- - 'p',
- - 'pre',
- - 'q',
- - 'rp',
- - 'rt',
- - 'ruby',
- - 'samp',
- - 'small',
- - 'small',
- - 'source',
- - 'span',
- - 'strike',
- - 'strong',
- - 'sub',
- - 'summary',
- - 'sup',
- - 'table',
- - 'tbody',
- - 'td',
- - 'tfoot',
- - 'th',
- - 'thead',
- - 'time',
- - 'tr',
- - 'tt',
- - 'u',
- - 'ul',
- - 'var',
- - 'video',
- - 'wbr',
- -]);
- + "a",
- + "abbr",
- + "b",
- + "bdo",
- + "blockquote",
- + "br",
- + "caption",
- + "cite",
- + "code",
- + "col",
- + "colgroup",
- + "dd",
- + "del",
- + "details",
- + "dfn",
- + "div",
- + "dl",
- + "dt",
- + "em",
- + "figcaption",
- + "figure",
- + "h1",
- + "h2",
- + "h3",
- + "h4",
- + "h5",
- + "h6",
- + "hr",
- + "i",
- + "img",
- + "input",
- + "ins",
- + "kbd",
- + "label",
- + "li",
- + "mark",
- + "ol",
- + "p",
- + "pre",
- + "q",
- + "rp",
- + "rt",
- + "ruby",
- + "samp",
- + "small",
- + "small",
- + "source",
- + "span",
- + "strike",
- + "strong",
- + "sub",
- + "summary",
- + "sup",
- + "table",
- + "tbody",
- + "td",
- + "tfoot",
- + "th",
- + "thead",
- + "time",
- + "tr",
- + "tt",
- + "u",
- + "ul",
- + "var",
- + "video",
- + "wbr",
- +])
-
- const defaultDomPurifyConfig = Object.freeze<dompurify.Config & { RETURN_TRUSTED_TYPE: true }>({
- - 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'],
- - 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'],
- + 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",
- + ],
- + 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",
- + ],
- RETURN_DOM: false,
- RETURN_DOM_FRAGMENT: false,
- - RETURN_TRUSTED_TYPE: true
- -});
- + RETURN_TRUSTED_TYPE: true,
- +})
-
- /**
- * Sanitizes the given `value` and reset the given `node` with it.
- */
- export function safeInnerHtml(node: HTMLElement, value: string, extraDomPurifyConfig?: dompurify.Config): void {
- - const hook = hookDomPurifyHrefAndSrcSanitizer(defaultSafeProtocols);
- + const hook = hookDomPurifyHrefAndSrcSanitizer(defaultSafeProtocols)
- try {
- - const html = dompurify.sanitize(value, { ...defaultDomPurifyConfig, ...extraDomPurifyConfig });
- - node.innerHTML = html as unknown as string;
- + const html = dompurify.sanitize(value, { ...defaultDomPurifyConfig, ...extraDomPurifyConfig })
- + node.innerHTML = html as unknown as string
- } finally {
- - hook.dispose();
- + hook.dispose()
- }
- }
-
- @@ -1798,16 +1975,16 @@ export function safeInnerHtml(node: HTMLElement, value: string, extraDomPurifyCo
- * From https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/btoa
- */
- function toBinary(str: string): string {
- - const codeUnits = new Uint16Array(str.length);
- + const codeUnits = new Uint16Array(str.length)
- for (let i = 0; i < codeUnits.length; i++) {
- - codeUnits[i] = str.charCodeAt(i);
- + codeUnits[i] = str.charCodeAt(i)
- }
- - let binary = '';
- - const uint8array = new Uint8Array(codeUnits.buffer);
- + let binary = ""
- + const uint8array = new Uint8Array(codeUnits.buffer)
- for (let i = 0; i < uint8array.length; i++) {
- - binary += String.fromCharCode(uint8array[i]);
- + binary += String.fromCharCode(uint8array[i])
- }
- - return binary;
- + return binary
- }
-
- /**
- @@ -1815,143 +1992,185 @@ function toBinary(str: string): string {
- * of throwing an exception.
- */
- export function multibyteAwareBtoa(str: string): string {
- - return btoa(toBinary(str));
- + return btoa(toBinary(str))
- }
-
- -type ModifierKey = 'alt' | 'ctrl' | 'shift' | 'meta';
- +type ModifierKey = "alt" | "ctrl" | "shift" | "meta"
-
- export interface IModifierKeyStatus {
- - altKey: boolean;
- - shiftKey: boolean;
- - ctrlKey: boolean;
- - metaKey: boolean;
- - lastKeyPressed?: ModifierKey;
- - lastKeyReleased?: ModifierKey;
- - event?: KeyboardEvent;
- + altKey: boolean
- + shiftKey: boolean
- + ctrlKey: boolean
- + metaKey: boolean
- + lastKeyPressed?: ModifierKey
- + lastKeyReleased?: ModifierKey
- + event?: KeyboardEvent
- }
-
- export class ModifierKeyEmitter extends event.Emitter<IModifierKeyStatus> {
- -
- - private readonly _subscriptions = new DisposableStore();
- - private _keyStatus: IModifierKeyStatus;
- - private static instance: ModifierKeyEmitter;
- + private readonly _subscriptions = new DisposableStore()
- + private _keyStatus: IModifierKeyStatus
- + private static instance: ModifierKeyEmitter
-
- private constructor() {
- - super();
- + super()
-
- this._keyStatus = {
- altKey: false,
- shiftKey: false,
- ctrlKey: false,
- - metaKey: false
- - };
- + metaKey: false,
- + }
-
- - this._subscriptions.add(event.Event.runAndSubscribe(onDidRegisterWindow, ({ window, disposables }) => this.registerListeners(window, disposables), { window: mainWindow, disposables: this._subscriptions }));
- + this._subscriptions.add(
- + event.Event.runAndSubscribe(
- + onDidRegisterWindow,
- + ({ window, disposables }) => this.registerListeners(window, disposables),
- + { window: mainWindow, disposables: this._subscriptions },
- + ),
- + )
- }
-
- private registerListeners(window: Window, disposables: DisposableStore): void {
- - disposables.add(addDisposableListener(window, 'keydown', e => {
- - if (e.defaultPrevented) {
- - return;
- - }
- -
- - const event = new StandardKeyboardEvent(e);
- - // If Alt-key keydown event is repeated, ignore it #112347
- - // Only known to be necessary for Alt-Key at the moment #115810
- - if (event.keyCode === KeyCode.Alt && e.repeat) {
- - return;
- - }
- -
- - if (e.altKey && !this._keyStatus.altKey) {
- - this._keyStatus.lastKeyPressed = 'alt';
- - } else if (e.ctrlKey && !this._keyStatus.ctrlKey) {
- - this._keyStatus.lastKeyPressed = 'ctrl';
- - } else if (e.metaKey && !this._keyStatus.metaKey) {
- - this._keyStatus.lastKeyPressed = 'meta';
- - } else if (e.shiftKey && !this._keyStatus.shiftKey) {
- - this._keyStatus.lastKeyPressed = 'shift';
- - } else if (event.keyCode !== KeyCode.Alt) {
- - this._keyStatus.lastKeyPressed = undefined;
- - } else {
- - return;
- - }
- -
- - this._keyStatus.altKey = e.altKey;
- - this._keyStatus.ctrlKey = e.ctrlKey;
- - this._keyStatus.metaKey = e.metaKey;
- - this._keyStatus.shiftKey = e.shiftKey;
- + disposables.add(
- + addDisposableListener(
- + window,
- + "keydown",
- + (e) => {
- + if (e.defaultPrevented) {
- + return
- + }
-
- - if (this._keyStatus.lastKeyPressed) {
- - this._keyStatus.event = e;
- - this.fire(this._keyStatus);
- - }
- - }, true));
- + const event = new StandardKeyboardEvent(e)
- + // If Alt-key keydown event is repeated, ignore it #112347
- + // Only known to be necessary for Alt-Key at the moment #115810
- + if (event.keyCode === KeyCode.Alt && e.repeat) {
- + return
- + }
-
- - disposables.add(addDisposableListener(window, 'keyup', e => {
- - if (e.defaultPrevented) {
- - return;
- - }
- + if (e.altKey && !this._keyStatus.altKey) {
- + this._keyStatus.lastKeyPressed = "alt"
- + } else if (e.ctrlKey && !this._keyStatus.ctrlKey) {
- + this._keyStatus.lastKeyPressed = "ctrl"
- + } else if (e.metaKey && !this._keyStatus.metaKey) {
- + this._keyStatus.lastKeyPressed = "meta"
- + } else if (e.shiftKey && !this._keyStatus.shiftKey) {
- + this._keyStatus.lastKeyPressed = "shift"
- + } else if (event.keyCode !== KeyCode.Alt) {
- + this._keyStatus.lastKeyPressed = undefined
- + } else {
- + return
- + }
-
- - if (!e.altKey && this._keyStatus.altKey) {
- - this._keyStatus.lastKeyReleased = 'alt';
- - } else if (!e.ctrlKey && this._keyStatus.ctrlKey) {
- - this._keyStatus.lastKeyReleased = 'ctrl';
- - } else if (!e.metaKey && this._keyStatus.metaKey) {
- - this._keyStatus.lastKeyReleased = 'meta';
- - } else if (!e.shiftKey && this._keyStatus.shiftKey) {
- - this._keyStatus.lastKeyReleased = 'shift';
- - } else {
- - this._keyStatus.lastKeyReleased = undefined;
- - }
- + this._keyStatus.altKey = e.altKey
- + this._keyStatus.ctrlKey = e.ctrlKey
- + this._keyStatus.metaKey = e.metaKey
- + this._keyStatus.shiftKey = e.shiftKey
-
- - if (this._keyStatus.lastKeyPressed !== this._keyStatus.lastKeyReleased) {
- - this._keyStatus.lastKeyPressed = undefined;
- - }
- + if (this._keyStatus.lastKeyPressed) {
- + this._keyStatus.event = e
- + this.fire(this._keyStatus)
- + }
- + },
- + true,
- + ),
- + )
-
- - this._keyStatus.altKey = e.altKey;
- - this._keyStatus.ctrlKey = e.ctrlKey;
- - this._keyStatus.metaKey = e.metaKey;
- - this._keyStatus.shiftKey = e.shiftKey;
- + disposables.add(
- + addDisposableListener(
- + window,
- + "keyup",
- + (e) => {
- + if (e.defaultPrevented) {
- + return
- + }
-
- - if (this._keyStatus.lastKeyReleased) {
- - this._keyStatus.event = e;
- - this.fire(this._keyStatus);
- - }
- - }, true));
- + if (!e.altKey && this._keyStatus.altKey) {
- + this._keyStatus.lastKeyReleased = "alt"
- + } else if (!e.ctrlKey && this._keyStatus.ctrlKey) {
- + this._keyStatus.lastKeyReleased = "ctrl"
- + } else if (!e.metaKey && this._keyStatus.metaKey) {
- + this._keyStatus.lastKeyReleased = "meta"
- + } else if (!e.shiftKey && this._keyStatus.shiftKey) {
- + this._keyStatus.lastKeyReleased = "shift"
- + } else {
- + this._keyStatus.lastKeyReleased = undefined
- + }
-
- - disposables.add(addDisposableListener(window.document.body, 'mousedown', () => {
- - this._keyStatus.lastKeyPressed = undefined;
- - }, true));
- + if (this._keyStatus.lastKeyPressed !== this._keyStatus.lastKeyReleased) {
- + this._keyStatus.lastKeyPressed = undefined
- + }
-
- - disposables.add(addDisposableListener(window.document.body, 'mouseup', () => {
- - this._keyStatus.lastKeyPressed = undefined;
- - }, true));
- + this._keyStatus.altKey = e.altKey
- + this._keyStatus.ctrlKey = e.ctrlKey
- + this._keyStatus.metaKey = e.metaKey
- + this._keyStatus.shiftKey = e.shiftKey
-
- - disposables.add(addDisposableListener(window.document.body, 'mousemove', e => {
- - if (e.buttons) {
- - this._keyStatus.lastKeyPressed = undefined;
- - }
- - }, true));
- + if (this._keyStatus.lastKeyReleased) {
- + this._keyStatus.event = e
- + this.fire(this._keyStatus)
- + }
- + },
- + true,
- + ),
- + )
- +
- + disposables.add(
- + addDisposableListener(
- + window.document.body,
- + "mousedown",
- + () => {
- + this._keyStatus.lastKeyPressed = undefined
- + },
- + true,
- + ),
- + )
- +
- + disposables.add(
- + addDisposableListener(
- + window.document.body,
- + "mouseup",
- + () => {
- + this._keyStatus.lastKeyPressed = undefined
- + },
- + true,
- + ),
- + )
- +
- + disposables.add(
- + addDisposableListener(
- + window.document.body,
- + "mousemove",
- + (e) => {
- + if (e.buttons) {
- + this._keyStatus.lastKeyPressed = undefined
- + }
- + },
- + true,
- + ),
- + )
-
- - disposables.add(addDisposableListener(window, 'blur', () => {
- - this.resetKeyStatus();
- - }));
- + disposables.add(
- + addDisposableListener(window, "blur", () => {
- + this.resetKeyStatus()
- + }),
- + )
- }
-
- get keyStatus(): IModifierKeyStatus {
- - return this._keyStatus;
- + return this._keyStatus
- }
-
- get isModifierPressed(): boolean {
- - return this._keyStatus.altKey || this._keyStatus.ctrlKey || this._keyStatus.metaKey || this._keyStatus.shiftKey;
- + return this._keyStatus.altKey || this._keyStatus.ctrlKey || this._keyStatus.metaKey || this._keyStatus.shiftKey
- }
-
- /**
- * Allows to explicitly reset the key status based on more knowledge (#109062)
- */
- resetKeyStatus(): void {
- - this.doResetKeyStatus();
- - this.fire(this._keyStatus);
- + this.doResetKeyStatus()
- + this.fire(this._keyStatus)
- }
-
- private doResetKeyStatus(): void {
- @@ -1959,139 +2178,158 @@ export class ModifierKeyEmitter extends event.Emitter<IModifierKeyStatus> {
- altKey: false,
- shiftKey: false,
- ctrlKey: false,
- - metaKey: false
- - };
- + metaKey: false,
- + }
- }
-
- static getInstance() {
- if (!ModifierKeyEmitter.instance) {
- - ModifierKeyEmitter.instance = new ModifierKeyEmitter();
- + ModifierKeyEmitter.instance = new ModifierKeyEmitter()
- }
-
- - return ModifierKeyEmitter.instance;
- + return ModifierKeyEmitter.instance
- }
-
- override dispose() {
- - super.dispose();
- - this._subscriptions.dispose();
- + super.dispose()
- + this._subscriptions.dispose()
- }
- }
-
- export function getCookieValue(name: string): string | undefined {
- - const match = document.cookie.match('(^|[^;]+)\\s*' + name + '\\s*=\\s*([^;]+)'); // See https://stackoverflow.com/a/25490531
- + const match = document.cookie.match("(^|[^;]+)\\s*" + name + "\\s*=\\s*([^;]+)") // See https://stackoverflow.com/a/25490531
-
- - return match ? match.pop() : undefined;
- + return match ? match.pop() : undefined
- }
-
- export interface IDragAndDropObserverCallbacks {
- - readonly onDragEnter?: (e: DragEvent) => void;
- - readonly onDragLeave?: (e: DragEvent) => void;
- - readonly onDrop?: (e: DragEvent) => void;
- - readonly onDragEnd?: (e: DragEvent) => void;
- - readonly onDragStart?: (e: DragEvent) => void;
- - readonly onDrag?: (e: DragEvent) => void;
- - readonly onDragOver?: (e: DragEvent, dragDuration: number) => void;
- + readonly onDragEnter?: (e: DragEvent) => void
- + readonly onDragLeave?: (e: DragEvent) => void
- + readonly onDrop?: (e: DragEvent) => void
- + readonly onDragEnd?: (e: DragEvent) => void
- + readonly onDragStart?: (e: DragEvent) => void
- + readonly onDrag?: (e: DragEvent) => void
- + readonly onDragOver?: (e: DragEvent, dragDuration: number) => void
- }
-
- export class DragAndDropObserver extends Disposable {
- -
- // A helper to fix issues with repeated DRAG_ENTER / DRAG_LEAVE
- // calls see https://github.com/microsoft/vscode/issues/14470
- // when the element has child elements where the events are fired
- // repeadedly.
- - private counter: number = 0;
- + private counter: number = 0
-
- // Allows to measure the duration of the drag operation.
- - private dragStartTime = 0;
- + private dragStartTime = 0
-
- - constructor(private readonly element: HTMLElement, private readonly callbacks: IDragAndDropObserverCallbacks) {
- - super();
- + constructor(
- + private readonly element: HTMLElement,
- + private readonly callbacks: IDragAndDropObserverCallbacks,
- + ) {
- + super()
-
- - this.registerListeners();
- + this.registerListeners()
- }
-
- private registerListeners(): void {
- if (this.callbacks.onDragStart) {
- - this._register(addDisposableListener(this.element, EventType.DRAG_START, (e: DragEvent) => {
- - this.callbacks.onDragStart?.(e);
- - }));
- + this._register(
- + addDisposableListener(this.element, EventType.DRAG_START, (e: DragEvent) => {
- + this.callbacks.onDragStart?.(e)
- + }),
- + )
- }
-
- if (this.callbacks.onDrag) {
- - this._register(addDisposableListener(this.element, EventType.DRAG, (e: DragEvent) => {
- - this.callbacks.onDrag?.(e);
- - }));
- + this._register(
- + addDisposableListener(this.element, EventType.DRAG, (e: DragEvent) => {
- + this.callbacks.onDrag?.(e)
- + }),
- + )
- }
-
- - this._register(addDisposableListener(this.element, EventType.DRAG_ENTER, (e: DragEvent) => {
- - this.counter++;
- - this.dragStartTime = e.timeStamp;
- + this._register(
- + addDisposableListener(this.element, EventType.DRAG_ENTER, (e: DragEvent) => {
- + this.counter++
- + this.dragStartTime = e.timeStamp
-
- - this.callbacks.onDragEnter?.(e);
- - }));
- + this.callbacks.onDragEnter?.(e)
- + }),
- + )
-
- - this._register(addDisposableListener(this.element, EventType.DRAG_OVER, (e: DragEvent) => {
- - e.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome)
- + this._register(
- + addDisposableListener(this.element, EventType.DRAG_OVER, (e: DragEvent) => {
- + e.preventDefault() // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome)
-
- - this.callbacks.onDragOver?.(e, e.timeStamp - this.dragStartTime);
- - }));
- + this.callbacks.onDragOver?.(e, e.timeStamp - this.dragStartTime)
- + }),
- + )
-
- - this._register(addDisposableListener(this.element, EventType.DRAG_LEAVE, (e: DragEvent) => {
- - this.counter--;
- + this._register(
- + addDisposableListener(this.element, EventType.DRAG_LEAVE, (e: DragEvent) => {
- + this.counter--
-
- - if (this.counter === 0) {
- - this.dragStartTime = 0;
- + if (this.counter === 0) {
- + this.dragStartTime = 0
-
- - this.callbacks.onDragLeave?.(e);
- - }
- - }));
- + this.callbacks.onDragLeave?.(e)
- + }
- + }),
- + )
-
- - this._register(addDisposableListener(this.element, EventType.DRAG_END, (e: DragEvent) => {
- - this.counter = 0;
- - this.dragStartTime = 0;
- + this._register(
- + addDisposableListener(this.element, EventType.DRAG_END, (e: DragEvent) => {
- + this.counter = 0
- + this.dragStartTime = 0
-
- - this.callbacks.onDragEnd?.(e);
- - }));
- + this.callbacks.onDragEnd?.(e)
- + }),
- + )
-
- - this._register(addDisposableListener(this.element, EventType.DROP, (e: DragEvent) => {
- - this.counter = 0;
- - this.dragStartTime = 0;
- + this._register(
- + addDisposableListener(this.element, EventType.DROP, (e: DragEvent) => {
- + this.counter = 0
- + this.dragStartTime = 0
-
- - this.callbacks.onDrop?.(e);
- - }));
- + this.callbacks.onDrop?.(e)
- + }),
- + )
- }
- }
-
- -type HTMLElementAttributeKeys<T> = Partial<{ [K in keyof T]: T[K] extends Function ? never : T[K] extends object ? HTMLElementAttributeKeys<T[K]> : T[K] }>;
- -type ElementAttributes<T> = HTMLElementAttributeKeys<T> & Record<string, any>;
- -type RemoveHTMLElement<T> = T extends HTMLElement ? never : T;
- -type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
- -type ArrayToObj<T extends readonly any[]> = UnionToIntersection<RemoveHTMLElement<T[number]>>;
- -type HHTMLElementTagNameMap = HTMLElementTagNameMap & { '': HTMLDivElement };
- +type HTMLElementAttributeKeys<T> = Partial<{
- + [K in keyof T]: T[K] extends Function ? never : T[K] extends object ? HTMLElementAttributeKeys<T[K]> : T[K]
- +}>
- +type ElementAttributes<T> = HTMLElementAttributeKeys<T> & Record<string, any>
- +type RemoveHTMLElement<T> = T extends HTMLElement ? never : T
- +type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never
- +type ArrayToObj<T extends readonly any[]> = UnionToIntersection<RemoveHTMLElement<T[number]>>
- +type HHTMLElementTagNameMap = HTMLElementTagNameMap & { "": HTMLDivElement }
-
- type TagToElement<T> = T extends `${infer TStart}#${string}`
- ? TStart extends keyof HHTMLElementTagNameMap
- - ? HHTMLElementTagNameMap[TStart]
- - : HTMLElement
- + ? HHTMLElementTagNameMap[TStart]
- + : HTMLElement
- : T extends `${infer TStart}.${string}`
- - ? TStart extends keyof HHTMLElementTagNameMap
- - ? HHTMLElementTagNameMap[TStart]
- - : HTMLElement
- - : T extends keyof HTMLElementTagNameMap
- - ? HTMLElementTagNameMap[T]
- - : HTMLElement;
- + ? TStart extends keyof HHTMLElementTagNameMap
- + ? HHTMLElementTagNameMap[TStart]
- + : HTMLElement
- + : T extends keyof HTMLElementTagNameMap
- + ? HTMLElementTagNameMap[T]
- + : HTMLElement
-
- type TagToElementAndId<TTag> = TTag extends `${infer TTag}@${infer TId}`
- ? { element: TagToElement<TTag>; id: TId }
- - : { element: TagToElement<TTag>; id: 'root' };
- + : { element: TagToElement<TTag>; id: "root" }
-
- -type TagToRecord<TTag> = TagToElementAndId<TTag> extends { element: infer TElement; id: infer TId }
- - ? Record<(TId extends string ? TId : never) | 'root', TElement>
- - : never;
- +type TagToRecord<TTag> =
- + TagToElementAndId<TTag> extends { element: infer TElement; id: infer TId }
- + ? Record<(TId extends string ? TId : never) | "root", TElement>
- + : never
-
- -type Child = HTMLElement | string | Record<string, HTMLElement>;
- +type Child = HTMLElement | string | Record<string, HTMLElement>
-
- -const H_REGEX = /(?<tag>[\w\-]+)?(?:#(?<id>[\w\-]+))?(?<class>(?:\.(?:[\w\-]+))*)(?:@(?<name>(?:[\w\_])+))?/;
- +const H_REGEX = /(?<tag>[\w\-]+)?(?:#(?<id>[\w\-]+))?(?<class>(?:\.(?:[\w\-]+))*)(?:@(?<name>(?:[\w\_])+))?/
-
- /**
- * A helper function to create nested dom nodes.
- @@ -2107,249 +2345,283 @@ const H_REGEX = /(?<tag>[\w\-]+)?(?:#(?<id>[\w\-]+))?(?<class>(?:\.(?:[\w\-]+))*
- * ]);
- * const editor = createEditor(elements.editor);
- * ```
- -*/
- -export function h<TTag extends string>
- - (tag: TTag):
- - TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
- -
- -export function h<TTag extends string, T extends Child[]>
- - (tag: TTag, children: [...T]):
- - (ArrayToObj<T> & TagToRecord<TTag>) extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
- -
- -export function h<TTag extends string>
- - (tag: TTag, attributes: Partial<ElementAttributes<TagToElement<TTag>>>):
- - TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
- -
- -export function h<TTag extends string, T extends Child[]>
- - (tag: TTag, attributes: Partial<ElementAttributes<TagToElement<TTag>>>, children: [...T]):
- - (ArrayToObj<T> & TagToRecord<TTag>) extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
- -
- -export function h(tag: string, ...args: [] | [attributes: { $: string } & Partial<ElementAttributes<HTMLElement>> | Record<string, any>, children?: any[]] | [children: any[]]): Record<string, HTMLElement> {
- - let attributes: { $?: string } & Partial<ElementAttributes<HTMLElement>>;
- - let children: (Record<string, HTMLElement> | HTMLElement)[] | undefined;
- + */
- +export function h<TTag extends string>(
- + tag: TTag,
- +): TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never
- +
- +export function h<TTag extends string, T extends Child[]>(
- + tag: TTag,
- + children: [...T],
- +): ArrayToObj<T> & TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never
- +
- +export function h<TTag extends string>(
- + tag: TTag,
- + attributes: Partial<ElementAttributes<TagToElement<TTag>>>,
- +): TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never
- +
- +export function h<TTag extends string, T extends Child[]>(
- + tag: TTag,
- + attributes: Partial<ElementAttributes<TagToElement<TTag>>>,
- + children: [...T],
- +): ArrayToObj<T> & TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never
- +
- +export function h(
- + tag: string,
- + ...args:
- + | []
- + | [
- + attributes: ({ $: string } & Partial<ElementAttributes<HTMLElement>>) | Record<string, any>,
- + children?: any[],
- + ]
- + | [children: any[]]
- +): Record<string, HTMLElement> {
- + let attributes: { $?: string } & Partial<ElementAttributes<HTMLElement>>
- + let children: (Record<string, HTMLElement> | HTMLElement)[] | undefined
-
- if (Array.isArray(args[0])) {
- - attributes = {};
- - children = args[0];
- + attributes = {}
- + children = args[0]
- } else {
- - attributes = args[0] as any || {};
- - children = args[1];
- + attributes = (args[0] as any) || {}
- + children = args[1]
- }
-
- - const match = H_REGEX.exec(tag);
- + const match = H_REGEX.exec(tag)
-
- if (!match || !match.groups) {
- - throw new Error('Bad use of h');
- + throw new Error("Bad use of h")
- }
-
- - const tagName = match.groups['tag'] || 'div';
- - const el = document.createElement(tagName);
- + const tagName = match.groups["tag"] || "div"
- + const el = document.createElement(tagName)
-
- - if (match.groups['id']) {
- - el.id = match.groups['id'];
- + if (match.groups["id"]) {
- + el.id = match.groups["id"]
- }
-
- - const classNames = [];
- - if (match.groups['class']) {
- - for (const className of match.groups['class'].split('.')) {
- - if (className !== '') {
- - classNames.push(className);
- + const classNames = []
- + if (match.groups["class"]) {
- + for (const className of match.groups["class"].split(".")) {
- + if (className !== "") {
- + classNames.push(className)
- }
- }
- }
- if (attributes.className !== undefined) {
- - for (const className of attributes.className.split('.')) {
- - if (className !== '') {
- - classNames.push(className);
- + for (const className of attributes.className.split(".")) {
- + if (className !== "") {
- + classNames.push(className)
- }
- }
- }
- if (classNames.length > 0) {
- - el.className = classNames.join(' ');
- + el.className = classNames.join(" ")
- }
-
- - const result: Record<string, HTMLElement> = {};
- + const result: Record<string, HTMLElement> = {}
-
- - if (match.groups['name']) {
- - result[match.groups['name']] = el;
- + if (match.groups["name"]) {
- + result[match.groups["name"]] = el
- }
-
- if (children) {
- for (const c of children) {
- if (isHTMLElement(c)) {
- - el.appendChild(c);
- - } else if (typeof c === 'string') {
- - el.append(c);
- - } else if ('root' in c) {
- - Object.assign(result, c);
- - el.appendChild(c.root);
- + el.appendChild(c)
- + } else if (typeof c === "string") {
- + el.append(c)
- + } else if ("root" in c) {
- + Object.assign(result, c)
- + el.appendChild(c.root)
- }
- }
- }
-
- for (const [key, value] of Object.entries(attributes)) {
- - if (key === 'className') {
- - continue;
- - } else if (key === 'style') {
- + if (key === "className") {
- + continue
- + } else if (key === "style") {
- for (const [cssKey, cssValue] of Object.entries(value)) {
- el.style.setProperty(
- camelCaseToHyphenCase(cssKey),
- - typeof cssValue === 'number' ? cssValue + 'px' : '' + cssValue
- - );
- + typeof cssValue === "number" ? cssValue + "px" : "" + cssValue,
- + )
- }
- - } else if (key === 'tabIndex') {
- - el.tabIndex = value;
- + } else if (key === "tabIndex") {
- + el.tabIndex = value
- } else {
- - el.setAttribute(camelCaseToHyphenCase(key), value.toString());
- + el.setAttribute(camelCaseToHyphenCase(key), value.toString())
- }
- }
-
- - result['root'] = el;
- + result["root"] = el
-
- - return result;
- + return result
- }
-
- /** @deprecated This is a duplication of the h function. Needs cleanup. */
- -export function svgElem<TTag extends string>
- - (tag: TTag):
- - TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
- +export function svgElem<TTag extends string>(
- + tag: TTag,
- +): TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never
- /** @deprecated This is a duplication of the h function. Needs cleanup. */
- -export function svgElem<TTag extends string, T extends Child[]>
- - (tag: TTag, children: [...T]):
- - (ArrayToObj<T> & TagToRecord<TTag>) extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
- +export function svgElem<TTag extends string, T extends Child[]>(
- + tag: TTag,
- + children: [...T],
- +): ArrayToObj<T> & TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never
- /** @deprecated This is a duplication of the h function. Needs cleanup. */
- -export function svgElem<TTag extends string>
- - (tag: TTag, attributes: Partial<ElementAttributes<TagToElement<TTag>>>):
- - TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
- +export function svgElem<TTag extends string>(
- + tag: TTag,
- + attributes: Partial<ElementAttributes<TagToElement<TTag>>>,
- +): TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never
- /** @deprecated This is a duplication of the h function. Needs cleanup. */
- -export function svgElem<TTag extends string, T extends Child[]>
- - (tag: TTag, attributes: Partial<ElementAttributes<TagToElement<TTag>>>, children: [...T]):
- - (ArrayToObj<T> & TagToRecord<TTag>) extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never;
- +export function svgElem<TTag extends string, T extends Child[]>(
- + tag: TTag,
- + attributes: Partial<ElementAttributes<TagToElement<TTag>>>,
- + children: [...T],
- +): ArrayToObj<T> & TagToRecord<TTag> extends infer Y ? { [TKey in keyof Y]: Y[TKey] } : never
- /** @deprecated This is a duplication of the h function. Needs cleanup. */
- -export function svgElem(tag: string, ...args: [] | [attributes: { $: string } & Partial<ElementAttributes<HTMLElement>> | Record<string, any>, children?: any[]] | [children: any[]]): Record<string, HTMLElement> {
- - let attributes: { $?: string } & Partial<ElementAttributes<HTMLElement>>;
- - let children: (Record<string, HTMLElement> | HTMLElement)[] | undefined;
- +export function svgElem(
- + tag: string,
- + ...args:
- + | []
- + | [
- + attributes: ({ $: string } & Partial<ElementAttributes<HTMLElement>>) | Record<string, any>,
- + children?: any[],
- + ]
- + | [children: any[]]
- +): Record<string, HTMLElement> {
- + let attributes: { $?: string } & Partial<ElementAttributes<HTMLElement>>
- + let children: (Record<string, HTMLElement> | HTMLElement)[] | undefined
-
- if (Array.isArray(args[0])) {
- - attributes = {};
- - children = args[0];
- + attributes = {}
- + children = args[0]
- } else {
- - attributes = args[0] as any || {};
- - children = args[1];
- + attributes = (args[0] as any) || {}
- + children = args[1]
- }
-
- - const match = H_REGEX.exec(tag);
- + const match = H_REGEX.exec(tag)
-
- if (!match || !match.groups) {
- - throw new Error('Bad use of h');
- + throw new Error("Bad use of h")
- }
-
- - const tagName = match.groups['tag'] || 'div';
- - const el = document.createElementNS('http://www.w3.org/2000/svg', tagName) as any as HTMLElement;
- + const tagName = match.groups["tag"] || "div"
- + const el = document.createElementNS("http://www.w3.org/2000/svg", tagName) as any as HTMLElement
-
- - if (match.groups['id']) {
- - el.id = match.groups['id'];
- + if (match.groups["id"]) {
- + el.id = match.groups["id"]
- }
-
- - const classNames = [];
- - if (match.groups['class']) {
- - for (const className of match.groups['class'].split('.')) {
- - if (className !== '') {
- - classNames.push(className);
- + const classNames = []
- + if (match.groups["class"]) {
- + for (const className of match.groups["class"].split(".")) {
- + if (className !== "") {
- + classNames.push(className)
- }
- }
- }
- if (attributes.className !== undefined) {
- - for (const className of attributes.className.split('.')) {
- - if (className !== '') {
- - classNames.push(className);
- + for (const className of attributes.className.split(".")) {
- + if (className !== "") {
- + classNames.push(className)
- }
- }
- }
- if (classNames.length > 0) {
- - el.className = classNames.join(' ');
- + el.className = classNames.join(" ")
- }
-
- - const result: Record<string, HTMLElement> = {};
- + const result: Record<string, HTMLElement> = {}
-
- - if (match.groups['name']) {
- - result[match.groups['name']] = el;
- + if (match.groups["name"]) {
- + result[match.groups["name"]] = el
- }
-
- if (children) {
- for (const c of children) {
- if (isHTMLElement(c)) {
- - el.appendChild(c);
- - } else if (typeof c === 'string') {
- - el.append(c);
- - } else if ('root' in c) {
- - Object.assign(result, c);
- - el.appendChild(c.root);
- + el.appendChild(c)
- + } else if (typeof c === "string") {
- + el.append(c)
- + } else if ("root" in c) {
- + Object.assign(result, c)
- + el.appendChild(c.root)
- }
- }
- }
-
- for (const [key, value] of Object.entries(attributes)) {
- - if (key === 'className') {
- - continue;
- - } else if (key === 'style') {
- + if (key === "className") {
- + continue
- + } else if (key === "style") {
- for (const [cssKey, cssValue] of Object.entries(value)) {
- el.style.setProperty(
- camelCaseToHyphenCase(cssKey),
- - typeof cssValue === 'number' ? cssValue + 'px' : '' + cssValue
- - );
- + typeof cssValue === "number" ? cssValue + "px" : "" + cssValue,
- + )
- }
- - } else if (key === 'tabIndex') {
- - el.tabIndex = value;
- + } else if (key === "tabIndex") {
- + el.tabIndex = value
- } else {
- - el.setAttribute(camelCaseToHyphenCase(key), value.toString());
- + el.setAttribute(camelCaseToHyphenCase(key), value.toString())
- }
- }
-
- - result['root'] = el;
- + result["root"] = el
-
- - return result;
- + return result
- }
-
- function camelCaseToHyphenCase(str: string) {
- - return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
- + return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()
- }
-
- export function copyAttributes(from: Element, to: Element, filter?: string[]): void {
- for (const { name, value } of from.attributes) {
- if (!filter || filter.includes(name)) {
- - to.setAttribute(name, value);
- + to.setAttribute(name, value)
- }
- }
- }
-
- function copyAttribute(from: Element, to: Element, name: string): void {
- - const value = from.getAttribute(name);
- + const value = from.getAttribute(name)
- if (value) {
- - to.setAttribute(name, value);
- + to.setAttribute(name, value)
- } else {
- - to.removeAttribute(name);
- + to.removeAttribute(name)
- }
- }
-
- export function trackAttributes(from: Element, to: Element, filter?: string[]): IDisposable {
- - copyAttributes(from, to, filter);
- + copyAttributes(from, to, filter)
-
- - const disposables = new DisposableStore();
- + const disposables = new DisposableStore()
-
- - disposables.add(sharedMutationObserver.observe(from, disposables, { attributes: true, attributeFilter: filter })(mutations => {
- - for (const mutation of mutations) {
- - if (mutation.type === 'attributes' && mutation.attributeName) {
- - copyAttribute(from, to, mutation.attributeName);
- - }
- - }
- - }));
- + disposables.add(
- + sharedMutationObserver.observe(from, disposables, { attributes: true, attributeFilter: filter })(
- + (mutations) => {
- + for (const mutation of mutations) {
- + if (mutation.type === "attributes" && mutation.attributeName) {
- + copyAttribute(from, to, mutation.attributeName)
- + }
- + }
- + },
- + ),
- + )
-
- - return disposables;
- + return disposables
- }
-
- export function isEditableElement(element: Element): boolean {
- - return element.tagName.toLowerCase() === 'input' || element.tagName.toLowerCase() === 'textarea' || isHTMLElement(element) && !!element.editContext;
- + return (
- + element.tagName.toLowerCase() === "input" ||
- + element.tagName.toLowerCase() === "textarea" ||
- + (isHTMLElement(element) && !!element.editContext)
- + )
- }
-
- /**
- @@ -2358,40 +2630,40 @@ export function isEditableElement(element: Element): boolean {
- */
- export class SafeTriangle {
- // 4 points (x, y), 8 length
- - private points = new Int16Array(8);
- + private points = new Int16Array(8)
-
- constructor(
- private readonly originX: number,
- private readonly originY: number,
- - target: HTMLElement
- + target: HTMLElement,
- ) {
- - const { top, left, right, bottom } = target.getBoundingClientRect();
- - const t = this.points;
- - let i = 0;
- + const { top, left, right, bottom } = target.getBoundingClientRect()
- + const t = this.points
- + let i = 0
-
- - t[i++] = left;
- - t[i++] = top;
- + t[i++] = left
- + t[i++] = top
-
- - t[i++] = right;
- - t[i++] = top;
- + t[i++] = right
- + t[i++] = top
-
- - t[i++] = left;
- - t[i++] = bottom;
- + t[i++] = left
- + t[i++] = bottom
-
- - t[i++] = right;
- - t[i++] = bottom;
- + t[i++] = right
- + t[i++] = bottom
- }
-
- public contains(x: number, y: number) {
- - const { points, originX, originY } = this;
- + const { points, originX, originY } = this
- for (let i = 0; i < 4; i++) {
- - const p1 = 2 * i;
- - const p2 = 2 * ((i + 1) % 4);
- + const p1 = 2 * i
- + const p2 = 2 * ((i + 1) % 4)
- if (isPointWithinTriangle(x, y, originX, originY, points[p1], points[p1 + 1], points[p2], points[p2 + 1])) {
- - return true;
- + return true
- }
- }
-
- - return false;
- + return false
- }
- }
- diff --git a/src/vs/base/common/uri.ts b/src/vs/base/common/uri.ts
- index 73a3aa6cd49..404070f038f 100644
- --- a/src/vs/base/common/uri.ts
- +++ b/src/vs/base/common/uri.ts
- @@ -21,6 +21,7 @@ function _validateUri(ret: URI, _strict?: boolean): void {
-
- // scheme, https://tools.ietf.org/html/rfc3986#section-3.1
- // ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
- + // console.log('validate uri', ret.scheme);
- if (ret.scheme && !_schemePattern.test(ret.scheme)) {
- throw new Error('[UriError]: Scheme contains illegal characters.');
- }
- diff --git a/src/vs/base/parts/ipc/common/ipc.net.ts b/src/vs/base/parts/ipc/common/ipc.net.ts
- index 1bc63ba6878..b31f1260a5f 100644
- --- a/src/vs/base/parts/ipc/common/ipc.net.ts
- +++ b/src/vs/base/parts/ipc/common/ipc.net.ts
- @@ -3,6 +3,9 @@
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
-
- +import { fileLoggerGlobal } from '../../../../../../../src/extension.js';
- +import { FileRPCProtocolLogger } from '../../../../workbench/services/extensions/common/fileRPCProtocolLogger.js';
- +import { RequestInitiator } from '../../../../workbench/services/extensions/common/rpcProtocol.js';
- import { VSBuffer } from '../../../common/buffer.js';
- import { Emitter, Event } from '../../../common/event.js';
- import { Disposable, DisposableStore, IDisposable } from '../../../common/lifecycle.js';
- @@ -281,7 +284,7 @@ function protocolMessageTypeToString(messageType: ProtocolMessageType) {
- }
-
- export const enum ProtocolConstants {
- - HeaderLength = 13,
- +HeaderLength = 13,
- /**
- * Send an Acknowledge message at most 2 seconds later...
- */
- @@ -353,13 +356,14 @@ class ProtocolReader extends Disposable {
-
- public acceptChunk(data: VSBuffer | null): void {
- if (!data || data.byteLength === 0) {
- + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'Accept chunk: empty buffer');
- return;
- }
- + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'Accept chunk: ' + data.byteLength + ', read head: ' + this._state.readHead + ', read len: ' + this._state.readLen);
-
- this.lastReadTime = Date.now();
-
- this._incomingData.acceptChunk(data);
- -
- while (this._incomingData.byteLength >= this._state.readLen) {
-
- const buff = this._incomingData.read(this._state.readLen);
- @@ -373,6 +377,7 @@ class ProtocolReader extends Disposable {
- this._state.messageType = buff.readUInt8(0);
- this._state.id = buff.readUInt32BE(1);
- this._state.ack = buff.readUInt32BE(5);
- + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'Protocol header read: ' + this._state.id);
-
- this._socket.traceSocketEvent(SocketDiagnosticsEventType.ProtocolHeaderRead, { messageType: protocolMessageTypeToString(this._state.messageType), id: this._state.id, ack: this._state.ack, messageSize: this._state.readLen });
-
- @@ -388,6 +393,7 @@ class ProtocolReader extends Disposable {
- this._state.messageType = ProtocolMessageType.None;
- this._state.id = 0;
- this._state.ack = 0;
- + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'Protocol message read: ' + id + ', type: ' + messageType + ', ack: ' + ack);
-
- this._socket.traceSocketEvent(SocketDiagnosticsEventType.ProtocolMessageRead, buff);
-
- @@ -832,6 +838,7 @@ export class PersistentProtocol implements IMessagePassingProtocol {
- private _socketReader: ProtocolReader;
- // eslint-disable-next-line local/code-no-potentially-unsafe-disposables
- private _socketDisposables: DisposableStore;
- + private _fileLogger: FileRPCProtocolLogger;
-
- private readonly _loadEstimator: ILoadEstimator;
- private readonly _shouldSendKeepAlive: boolean;
- @@ -878,7 +885,7 @@ export class PersistentProtocol implements IMessagePassingProtocol {
- this._socketReader = this._socketDisposables.add(new ProtocolReader(this._socket));
- this._socketDisposables.add(this._socketReader.onMessage(msg => this._receiveMessage(msg)));
- this._socketDisposables.add(this._socket.onClose(e => this._onSocketClose.fire(e)));
- -
- + this._fileLogger = new FileRPCProtocolLogger('PersistentProtocol');
- if (opts.initialChunk) {
- this._socketReader.acceptChunk(opts.initialChunk);
- }
- @@ -944,6 +951,7 @@ export class PersistentProtocol implements IMessagePassingProtocol {
- }
-
- public beginAcceptReconnection(socket: ISocket, initialDataChunk: VSBuffer | null): void {
- + this._fileLogger.logIncoming(0, 0, RequestInitiator.LocalSide, 'Begin accept reconnection');
- this._isReconnecting = true;
-
- this._socketDisposables.dispose();
- @@ -966,6 +974,7 @@ export class PersistentProtocol implements IMessagePassingProtocol {
- }
-
- public endAcceptReconnection(): void {
- + this._fileLogger.logIncoming(0, 0, RequestInitiator.LocalSide, 'End accept reconnection');
- this._isReconnecting = false;
-
- // After a reconnection, let the other party know (again) which messages have been received.
- @@ -987,6 +996,7 @@ export class PersistentProtocol implements IMessagePassingProtocol {
- }
-
- private _receiveMessage(msg: ProtocolMessage): void {
- + this._fileLogger.logIncoming(0, 0, RequestInitiator.LocalSide, 'Receive message: ' + msg.type + ', id: ' + msg.id + ', ack: ' + msg.ack + ', data: ' + msg.data.byteLength + ', _incomingMsgId: ' + this._incomingMsgId);
- if (msg.ack > this._outgoingAckId) {
- this._outgoingAckId = msg.ack;
- do {
- diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts
- index 79a1112b410..cb4f3bce86d 100644
- --- a/src/vs/workbench/api/common/extHost.api.impl.ts
- +++ b/src/vs/workbench/api/common/extHost.api.impl.ts
- @@ -1241,14 +1241,14 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
- checkProposedApiEnabled(extension, 'canonicalUriProvider');
- return extHostWorkspace.provideCanonicalUri(uri, options, token);
- },
- - decode(content: Uint8Array, uri: vscode.Uri | undefined, options?: { encoding: string }) {
- + decode: function(content: Uint8Array): Thenable<string> {
- checkProposedApiEnabled(extension, 'textDocumentEncoding');
- - return extHostWorkspace.decode(content, uri, options);
- + return extHostWorkspace.decode(content, undefined, undefined);
- },
- - encode(content: string, uri: vscode.Uri | undefined, options?: { encoding: string }) {
- + encode: function(content: string): Thenable<Uint8Array> {
- checkProposedApiEnabled(extension, 'textDocumentEncoding');
- - return extHostWorkspace.encode(content, uri, options);
- - }
- + return extHostWorkspace.encode(content, undefined, undefined);
- + },
- };
-
- // namespace: scm
- @@ -1837,3 +1837,4 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
- };
- };
- }
- +
- diff --git a/src/vs/workbench/api/common/extHostConfiguration.ts b/src/vs/workbench/api/common/extHostConfiguration.ts
- index f0d9124a0da..943bda43fe3 100644
- --- a/src/vs/workbench/api/common/extHostConfiguration.ts
- +++ b/src/vs/workbench/api/common/extHostConfiguration.ts
- @@ -159,6 +159,7 @@ export class ExtHostConfigProvider {
- }
-
- getConfiguration(section?: string, scope?: vscode.ConfigurationScope | null, extensionDescription?: IExtensionDescription): vscode.WorkspaceConfiguration {
- + console.log('getConfiguration', section, scope, extensionDescription);
- const overrides = scopeToOverrides(scope) || {};
- const config = this._toReadonlyValue(this._configuration.getValue(section, overrides, this._extHostWorkspace.workspace));
-
- diff --git a/src/vs/workbench/api/common/extHostExtensionActivator.ts b/src/vs/workbench/api/common/extHostExtensionActivator.ts
- index 20f8efbfdbd..ad10b82ab40 100644
- --- a/src/vs/workbench/api/common/extHostExtensionActivator.ts
- +++ b/src/vs/workbench/api/common/extHostExtensionActivator.ts
- @@ -11,6 +11,8 @@ import { ExtensionIdentifier, ExtensionIdentifierMap } from '../../../platform/e
- import { ExtensionActivationReason, MissingExtensionDependency } from '../../services/extensions/common/extensions.js';
- import { ILogService } from '../../../platform/log/common/log.js';
- import { Barrier } from '../../../base/common/async.js';
- +import { fileLoggerGlobal } from '../../../../../../src/extension.js';
- +import { RequestInitiator } from '../../services/extensions/common/rpcProtocol.js';
-
- /**
- * Represents the source code (module) of an extension.
- @@ -229,7 +231,9 @@ export class ExtensionsActivator implements IDisposable {
- }
-
- public activateById(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void> {
- + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'activateById start: ' + extensionId.value);
- const desc = this._registry.getExtensionDescription(extensionId);
- + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'activateById desc: ' + desc);
- if (!desc) {
- throw new Error(`Extension '${extensionId.value}' is not known`);
- }
- diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts
- index 03aabb46045..9d85ddf4d40 100644
- --- a/src/vs/workbench/api/common/extHostExtensionService.ts
- +++ b/src/vs/workbench/api/common/extHostExtensionService.ts
- @@ -48,6 +48,8 @@ import { StopWatch } from '../../../base/common/stopwatch.js';
- import { isCI, setTimeout0 } from '../../../base/common/platform.js';
- import { IExtHostManagedSockets } from './extHostManagedSockets.js';
- import { Dto } from '../../services/extensions/common/proxyIdentifier.js';
- +import { fileLoggerGlobal } from '../../../../../../src/extension.js';
- +import { RequestInitiator } from '../../services/extensions/common/rpcProtocol.js';
-
- interface ITestRunner {
- /** Old test runner API, as exported from `vscode/lib/testrunner` */
- @@ -298,6 +300,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
- }
-
- private _activateByEvent(activationEvent: string, startup: boolean): Promise<void> {
- + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, '_activateByEvent: ' + activationEvent);
- return this._activator.activateByEvent(activationEvent, startup);
- }
-
- @@ -647,15 +650,19 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
- }
-
- private _activateAllStartupFinished(): void {
- + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'activateAllStartupFinished start');
- // startup is considered finished
- this._mainThreadExtensionsProxy.$setPerformanceMarks(performance.getMarks());
-
- this._extHostConfiguration.getConfigProvider().then((configProvider) => {
- + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'activateAllStartupFinished getConfigProvider');
- const shouldDeferActivation = configProvider.getConfiguration('extensions.experimental').get<boolean>('deferredStartupFinishedActivation');
- const allExtensionDescriptions = this._myRegistry.getAllExtensionDescriptions();
- if (shouldDeferActivation) {
- + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'activateAllStartupFinished shouldDeferActivation');
- this._activateAllStartupFinishedDeferred(allExtensionDescriptions);
- } else {
- + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'activateAllStartupFinished !shouldDeferActivation');
- for (const desc of allExtensionDescriptions) {
- if (desc.activationEvents) {
- for (const activationEvent of desc.activationEvents) {
- @@ -671,6 +678,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
-
- // Handle "eager" activation extensions
- private _handleEagerExtensions(): Promise<void> {
- + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'handleEagerExtensions start');
- const starActivation = this._activateByEvent('*', true).then(undefined, (err) => {
- this._logService.error(err);
- });
- @@ -689,6 +697,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
- }
-
- private _handleWorkspaceContainsEagerExtensions(folders: ReadonlyArray<vscode.WorkspaceFolder>): Promise<void> {
- + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'handleWorkspaceContainsEagerExtensions start: ' + folders.length);
- if (folders.length === 0) {
- return Promise.resolve(undefined);
- }
- @@ -697,7 +706,9 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
- this._myRegistry.getAllExtensionDescriptions().map((desc) => {
- return this._handleWorkspaceContainsEagerExtension(folders, desc);
- })
- - ).then(() => { });
- + ).then(() => {
- + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'handleWorkspaceContainsEagerExtensions end');
- + });
- }
-
- private async _handleWorkspaceContainsEagerExtension(folders: ReadonlyArray<vscode.WorkspaceFolder>, desc: IExtensionDescription): Promise<void> {
- @@ -726,6 +737,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
- }
-
- private async _handleRemoteResolverEagerExtensions(): Promise<void> {
- + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'handleRemoteResolverEagerExtensions start');
- if (this._initData.remote.authority) {
- return this._activateByEvent(`onResolveRemoteAuthority:${this._initData.remote.authority}`, false);
- }
- @@ -803,7 +815,9 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
- }
-
- private _startExtensionHost(): Promise<void> {
- + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'startExtensionHost start');
- if (this._started) {
- + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'Extension host is already started!');
- throw new Error(`Extension host is already started!`);
- }
- this._started = true;
- @@ -1036,6 +1050,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
- }
-
- public async $activate(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<boolean> {
- + console.log('activate', extensionId, reason);
- await this._readyToRunExtensions.wait();
- if (!this._myRegistry.getExtensionDescription(extensionId)) {
- // unknown extension => ignore
- diff --git a/src/vs/workbench/api/common/extHostWebview.ts b/src/vs/workbench/api/common/extHostWebview.ts
- index 435df4b03fc..1b85d76d832 100644
- --- a/src/vs/workbench/api/common/extHostWebview.ts
- +++ b/src/vs/workbench/api/common/extHostWebview.ts
- @@ -222,6 +222,7 @@ export class ExtHostWebviews extends Disposable implements extHostProtocol.ExtHo
- jsonMessage: string,
- buffers: SerializableObjectWithBuffers<VSBuffer[]>
- ): void {
- + console.log('onMessage', handle, jsonMessage, buffers);
- const webview = this.getWebview(handle);
- if (webview) {
- const { message } = deserializeWebviewMessage(jsonMessage, buffers.value);
- diff --git a/src/vs/workbench/api/common/extHostWebviewView.ts b/src/vs/workbench/api/common/extHostWebviewView.ts
- index 4696f33c5fa..e30033615aa 100644
- --- a/src/vs/workbench/api/common/extHostWebviewView.ts
- +++ b/src/vs/workbench/api/common/extHostWebviewView.ts
- @@ -12,6 +12,8 @@ import { ViewBadge } from './extHostTypeConverters.js';
- import type * as vscode from 'vscode';
- import * as extHostProtocol from './extHost.protocol.js';
- import * as extHostTypes from './extHostTypes.js';
- +import { fileLoggerGlobal } from '../../../../../../src/extension.js';
- +import { RequestInitiator } from '../../services/extensions/common/rpcProtocol.js';
-
- /* eslint-disable local/code-no-native-private */
-
- @@ -162,6 +164,7 @@ export class ExtHostWebviewViews implements extHostProtocol.ExtHostWebviewViewsS
- retainContextWhenHidden?: boolean;
- },
- ): vscode.Disposable {
- + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'registerWebviewViewProvider start: ' + viewType);
- if (this._viewProviders.has(viewType)) {
- throw new Error(`View provider for '${viewType}' already registered`);
- }
- @@ -185,6 +188,8 @@ export class ExtHostWebviewViews implements extHostProtocol.ExtHostWebviewViewsS
- state: any,
- cancellation: CancellationToken,
- ): Promise<void> {
- + console.log('resolveWebviewView', webviewHandle, viewType, title, state);
- + fileLoggerGlobal.logIncoming(0, 0, RequestInitiator.LocalSide, 'resolveWebviewView start: ' + viewType);
- const entry = this._viewProviders.get(viewType);
- if (!entry) {
- throw new Error(`No view provider found for '${viewType}'`);
- diff --git a/src/vs/workbench/api/common/extHostWorkspace.ts b/src/vs/workbench/api/common/extHostWorkspace.ts
- index 12af1c17f95..2e2b55b1fa4 100644
- --- a/src/vs/workbench/api/common/extHostWorkspace.ts
- +++ b/src/vs/workbench/api/common/extHostWorkspace.ts
- @@ -227,6 +227,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac
- }
-
- $initializeWorkspace(data: IWorkspaceData | null, trusted: boolean): void {
- + console.log('initializeWorkspace', data, trusted);
- this._trusted = trusted;
- this.$acceptWorkspaceData(data);
- this._barrier.open();
- diff --git a/src/vs/workbench/api/common/extensionHostMain.ts b/src/vs/workbench/api/common/extensionHostMain.ts
- index 11980f9aafe..24d9a7aeca4 100644
- --- a/src/vs/workbench/api/common/extensionHostMain.ts
- +++ b/src/vs/workbench/api/common/extensionHostMain.ts
- @@ -3,220 +3,236 @@
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
-
- -import * as errors from '../../../base/common/errors.js';
- -import * as performance from '../../../base/common/performance.js';
- -import { URI } from '../../../base/common/uri.js';
- -import { IURITransformer } from '../../../base/common/uriIpc.js';
- -import { IMessagePassingProtocol } from '../../../base/parts/ipc/common/ipc.js';
- -import { MainContext, MainThreadConsoleShape } from './extHost.protocol.js';
- -import { IExtensionHostInitData } from '../../services/extensions/common/extensionHostProtocol.js';
- -import { RPCProtocol } from '../../services/extensions/common/rpcProtocol.js';
- -import { ExtensionError, ExtensionIdentifier, IExtensionDescription } from '../../../platform/extensions/common/extensions.js';
- -import { ILogService } from '../../../platform/log/common/log.js';
- -import { getSingletonServiceDescriptors } from '../../../platform/instantiation/common/extensions.js';
- -import { ServiceCollection } from '../../../platform/instantiation/common/serviceCollection.js';
- -import { IExtHostInitDataService } from './extHostInitDataService.js';
- -import { InstantiationService } from '../../../platform/instantiation/common/instantiationService.js';
- -import { IInstantiationService, ServicesAccessor } from '../../../platform/instantiation/common/instantiation.js';
- -import { IExtHostRpcService, ExtHostRpcService } from './extHostRpcService.js';
- -import { IURITransformerService, URITransformerService } from './extHostUriTransformerService.js';
- -import { IExtHostExtensionService, IHostUtils } from './extHostExtensionService.js';
- -import { IExtHostTelemetry } from './extHostTelemetry.js';
- -import { Mutable } from '../../../base/common/types.js';
- +import * as errors from "../../../base/common/errors.js"
- +import * as performance from "../../../base/common/performance.js"
- +import { URI } from "../../../base/common/uri.js"
- +import { IURITransformer } from "../../../base/common/uriIpc.js"
- +import { IMessagePassingProtocol } from "../../../base/parts/ipc/common/ipc.js"
- +import { MainContext, MainThreadConsoleShape } from "./extHost.protocol.js"
- +import { IExtensionHostInitData } from "../../services/extensions/common/extensionHostProtocol.js"
- +import { RPCProtocol } from "../../services/extensions/common/rpcProtocol.js"
- +import {
- + ExtensionError,
- + ExtensionIdentifier,
- + IExtensionDescription,
- +} from "../../../platform/extensions/common/extensions.js"
- +import { ILogService } from "../../../platform/log/common/log.js"
- +import { getSingletonServiceDescriptors } from "../../../platform/instantiation/common/extensions.js"
- +import { ServiceCollection } from "../../../platform/instantiation/common/serviceCollection.js"
- +import { IExtHostInitDataService } from "./extHostInitDataService.js"
- +import { InstantiationService } from "../../../platform/instantiation/common/instantiationService.js"
- +import { IInstantiationService, ServicesAccessor } from "../../../platform/instantiation/common/instantiation.js"
- +import { IExtHostRpcService, ExtHostRpcService } from "./extHostRpcService.js"
- +import { IURITransformerService, URITransformerService } from "./extHostUriTransformerService.js"
- +import { IExtHostExtensionService, IHostUtils } from "./extHostExtensionService.js"
- +import { IExtHostTelemetry } from "./extHostTelemetry.js"
- +import { Mutable } from "../../../base/common/types.js"
- +import { FileRPCProtocolLogger } from "../../services/extensions/common/fileRPCProtocolLogger.js"
-
- export interface IExitFn {
- - (code?: number): any;
- + (code?: number): any
- }
-
- export interface IConsolePatchFn {
- - (mainThreadConsole: MainThreadConsoleShape): any;
- + (mainThreadConsole: MainThreadConsoleShape): any
- }
-
- export abstract class ErrorHandler {
- -
- static async installEarlyHandler(accessor: ServicesAccessor): Promise<void> {
- -
- // increase number of stack frames (from 10, https://github.com/v8/v8/wiki/Stack-Trace-API)
- - Error.stackTraceLimit = 100;
- + Error.stackTraceLimit = 100
-
- // does NOT dependent of extension information, can be installed immediately, and simply forwards
- // to the log service and main thread errors
- - const logService = accessor.get(ILogService);
- - const rpcService = accessor.get(IExtHostRpcService);
- - const mainThreadErrors = rpcService.getProxy(MainContext.MainThreadErrors);
- -
- - errors.setUnexpectedErrorHandler(err => {
- - logService.error(err);
- - const data = errors.transformErrorForSerialization(err);
- - mainThreadErrors.$onUnexpectedError(data);
- - });
- + const logService = accessor.get(ILogService)
- + const rpcService = accessor.get(IExtHostRpcService)
- + const mainThreadErrors = rpcService.getProxy(MainContext.MainThreadErrors)
- +
- + errors.setUnexpectedErrorHandler((err) => {
- + logService.error(err)
- + const data = errors.transformErrorForSerialization(err)
- + mainThreadErrors.$onUnexpectedError(data)
- + })
- }
-
- static async installFullHandler(accessor: ServicesAccessor): Promise<void> {
- // uses extension knowledges to correlate errors with extensions
-
- - const logService = accessor.get(ILogService);
- - const rpcService = accessor.get(IExtHostRpcService);
- - const extensionService = accessor.get(IExtHostExtensionService);
- - const extensionTelemetry = accessor.get(IExtHostTelemetry);
- + const logService = accessor.get(ILogService)
- + const rpcService = accessor.get(IExtHostRpcService)
- + const extensionService = accessor.get(IExtHostExtensionService)
- + const extensionTelemetry = accessor.get(IExtHostTelemetry)
-
- - const mainThreadExtensions = rpcService.getProxy(MainContext.MainThreadExtensionService);
- - const mainThreadErrors = rpcService.getProxy(MainContext.MainThreadErrors);
- + const mainThreadExtensions = rpcService.getProxy(MainContext.MainThreadExtensionService)
- + const mainThreadErrors = rpcService.getProxy(MainContext.MainThreadErrors)
-
- - const map = await extensionService.getExtensionPathIndex();
- - const extensionErrors = new WeakMap<Error, { extensionIdentifier: ExtensionIdentifier | undefined; stack: string }>();
- + const map = await extensionService.getExtensionPathIndex()
- + const extensionErrors = new WeakMap<
- + Error,
- + { extensionIdentifier: ExtensionIdentifier | undefined; stack: string }
- + >()
-
- // PART 1
- // set the prepareStackTrace-handle and use it as a side-effect to associate errors
- // with extensions - this works by looking up callsites in the extension path index
- function prepareStackTraceAndFindExtension(error: Error, stackTrace: errors.V8CallSite[]) {
- if (extensionErrors.has(error)) {
- - return extensionErrors.get(error)!.stack;
- + return extensionErrors.get(error)!.stack
- }
- - let stackTraceMessage = '';
- - let extension: IExtensionDescription | undefined;
- - let fileName: string | null;
- + let stackTraceMessage = ""
- + let extension: IExtensionDescription | undefined
- + let fileName: string | null
- for (const call of stackTrace) {
- - stackTraceMessage += `\n\tat ${call.toString()}`;
- - fileName = call.getFileName();
- + stackTraceMessage += `\n\tat ${call.toString()}`
- + fileName = call.getFileName()
- if (!extension && fileName) {
- - extension = map.findSubstr(URI.file(fileName));
- + extension = map.findSubstr(URI.file(fileName))
- }
- }
- - const result = `${error.name || 'Error'}: ${error.message || ''}${stackTraceMessage}`;
- - extensionErrors.set(error, { extensionIdentifier: extension?.identifier, stack: result });
- - return result;
- + const result = `${error.name || "Error"}: ${error.message || ""}${stackTraceMessage}`
- + extensionErrors.set(error, { extensionIdentifier: extension?.identifier, stack: result })
- + return result
- }
-
- - const _wasWrapped = Symbol('prepareStackTrace wrapped');
- - let _prepareStackTrace = prepareStackTraceAndFindExtension;
- + const _wasWrapped = Symbol("prepareStackTrace wrapped")
- + let _prepareStackTrace = prepareStackTraceAndFindExtension
-
- - Object.defineProperty(Error, 'prepareStackTrace', {
- + Object.defineProperty(Error, "prepareStackTrace", {
- configurable: false,
- get() {
- - return _prepareStackTrace;
- + return _prepareStackTrace
- },
- set(v) {
- if (v === prepareStackTraceAndFindExtension || !v || v[_wasWrapped]) {
- - _prepareStackTrace = v || prepareStackTraceAndFindExtension;
- - return;
- + _prepareStackTrace = v || prepareStackTraceAndFindExtension
- + return
- }
-
- _prepareStackTrace = function (error, stackTrace) {
- - prepareStackTraceAndFindExtension(error, stackTrace);
- - return v.call(Error, error, stackTrace);
- - };
- + prepareStackTraceAndFindExtension(error, stackTrace)
- + return v.call(Error, error, stackTrace)
- + }
-
- - Object.assign(_prepareStackTrace, { [_wasWrapped]: true });
- + Object.assign(_prepareStackTrace, { [_wasWrapped]: true })
- },
- - });
- + })
-
- // PART 2
- // set the unexpectedErrorHandler and check for extensions that have been identified as
- // having caused the error. Note that the runtime order is actually reversed, the code
- // below accesses the stack-property which triggers the code above
- - errors.setUnexpectedErrorHandler(err => {
- - logService.error(err);
- + errors.setUnexpectedErrorHandler((err) => {
- + logService.error(err)
-
- - const errorData = errors.transformErrorForSerialization(err);
- + const errorData = errors.transformErrorForSerialization(err)
-
- - let extension: ExtensionIdentifier | undefined;
- + let extension: ExtensionIdentifier | undefined
- if (err instanceof ExtensionError) {
- - extension = err.extension;
- + extension = err.extension
- } else {
- - const stackData = extensionErrors.get(err);
- - extension = stackData?.extensionIdentifier;
- + const stackData = extensionErrors.get(err)
- + extension = stackData?.extensionIdentifier
- }
-
- if (extension) {
- - mainThreadExtensions.$onExtensionRuntimeError(extension, errorData);
- - const reported = extensionTelemetry.onExtensionError(extension, err);
- - logService.trace('forwarded error to extension?', reported, extension);
- + mainThreadExtensions.$onExtensionRuntimeError(extension, errorData)
- + const reported = extensionTelemetry.onExtensionError(extension, err)
- + logService.trace("forwarded error to extension?", reported, extension)
- }
- - });
- + })
-
- - errors.errorHandler.addListener(err => {
- - mainThreadErrors.$onUnexpectedError(err);
- - });
- + errors.errorHandler.addListener((err) => {
- + const data = errors.transformErrorForSerialization(err)
- + mainThreadErrors.$onUnexpectedError(data)
- + })
- }
- }
-
- export class ExtensionHostMain {
- -
- - private readonly _hostUtils: IHostUtils;
- - private readonly _rpcProtocol: RPCProtocol;
- - private readonly _extensionService: IExtHostExtensionService;
- - private readonly _logService: ILogService;
- + private readonly _hostUtils: IHostUtils
- + private readonly _rpcProtocol: RPCProtocol
- + private readonly _extensionService: IExtHostExtensionService
- + private readonly _logService: ILogService
-
- constructor(
- protocol: IMessagePassingProtocol,
- initData: IExtensionHostInitData,
- hostUtils: IHostUtils,
- uriTransformer: IURITransformer | null,
- - messagePorts?: ReadonlyMap<string, MessagePort>
- + messagePorts?: ReadonlyMap<string, MessagePort>,
- ) {
- - this._hostUtils = hostUtils;
- - this._rpcProtocol = new RPCProtocol(protocol, null, uriTransformer);
- + this._hostUtils = hostUtils
- + this._rpcProtocol = new RPCProtocol(protocol, new FileRPCProtocolLogger("extension_protocol"), uriTransformer)
-
- // ensure URIs are transformed and revived
- - initData = ExtensionHostMain._transform(initData, this._rpcProtocol);
- + initData = ExtensionHostMain._transform(initData, this._rpcProtocol)
-
- // bootstrap services
- - const services = new ServiceCollection(...getSingletonServiceDescriptors());
- - services.set(IExtHostInitDataService, { _serviceBrand: undefined, ...initData, messagePorts });
- - services.set(IExtHostRpcService, new ExtHostRpcService(this._rpcProtocol));
- - services.set(IURITransformerService, new URITransformerService(uriTransformer));
- - services.set(IHostUtils, hostUtils);
- + const services = new ServiceCollection(...getSingletonServiceDescriptors())
- + services.set(IExtHostInitDataService, { _serviceBrand: undefined, ...initData, messagePorts })
- + services.set(IExtHostRpcService, new ExtHostRpcService(this._rpcProtocol))
- + services.set(IURITransformerService, new URITransformerService(uriTransformer))
- + services.set(IHostUtils, hostUtils)
-
- - const instaService: IInstantiationService = new InstantiationService(services, true);
- + const instaService: IInstantiationService = new InstantiationService(services, true)
-
- - instaService.invokeFunction(ErrorHandler.installEarlyHandler);
- + instaService.invokeFunction(ErrorHandler.installEarlyHandler)
-
- // ugly self - inject
- - this._logService = instaService.invokeFunction(accessor => accessor.get(ILogService));
- + this._logService = instaService.invokeFunction((accessor) => accessor.get(ILogService))
-
- - performance.mark(`code/extHost/didCreateServices`);
- + performance.mark(`code/extHost/didCreateServices`)
- if (this._hostUtils.pid) {
- - this._logService.info(`Extension host with pid ${this._hostUtils.pid} started`);
- + this._logService.info(`Extension host with pid ${this._hostUtils.pid} started`)
- } else {
- - this._logService.info(`Extension host started`);
- + this._logService.info(`Extension host started`)
- }
- - this._logService.trace('initData', initData);
- + this._logService.trace("initData", initData)
-
- // ugly self - inject
- // must call initialize *after* creating the extension service
- // because `initialize` itself creates instances that depend on it
- - this._extensionService = instaService.invokeFunction(accessor => accessor.get(IExtHostExtensionService));
- - this._extensionService.initialize();
- + this._extensionService = instaService.invokeFunction((accessor) => accessor.get(IExtHostExtensionService))
- + this._extensionService.initialize()
-
- // install error handler that is extension-aware
- - instaService.invokeFunction(ErrorHandler.installFullHandler);
- + instaService.invokeFunction(ErrorHandler.installFullHandler)
- }
-
- async asBrowserUri(uri: URI): Promise<URI> {
- - const mainThreadExtensionsProxy = this._rpcProtocol.getProxy(MainContext.MainThreadExtensionService);
- - return URI.revive(await mainThreadExtensionsProxy.$asBrowserUri(uri));
- + const mainThreadExtensionsProxy = this._rpcProtocol.getProxy(MainContext.MainThreadExtensionService)
- + return URI.revive(await mainThreadExtensionsProxy.$asBrowserUri(uri))
- }
-
- terminate(reason: string): void {
- - this._extensionService.terminate(reason);
- + this._extensionService.terminate(reason)
- }
-
- private static _transform(initData: IExtensionHostInitData, rpcProtocol: RPCProtocol): IExtensionHostInitData {
- initData.extensions.allExtensions.forEach((ext) => {
- - (<Mutable<IExtensionDescription>>ext).extensionLocation = URI.revive(rpcProtocol.transformIncomingURIs(ext.extensionLocation));
- - });
- - initData.environment.appRoot = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.appRoot));
- - const extDevLocs = initData.environment.extensionDevelopmentLocationURI;
- + ;(<Mutable<IExtensionDescription>>ext).extensionLocation = URI.revive(
- + rpcProtocol.transformIncomingURIs(ext.extensionLocation),
- + )
- + })
- + initData.environment.appRoot = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.appRoot))
- + const extDevLocs = initData.environment.extensionDevelopmentLocationURI
- if (extDevLocs) {
- - initData.environment.extensionDevelopmentLocationURI = extDevLocs.map(url => URI.revive(rpcProtocol.transformIncomingURIs(url)));
- + initData.environment.extensionDevelopmentLocationURI = extDevLocs.map((url) =>
- + URI.revive(rpcProtocol.transformIncomingURIs(url)),
- + )
- }
- - initData.environment.extensionTestsLocationURI = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.extensionTestsLocationURI));
- - initData.environment.globalStorageHome = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.globalStorageHome));
- - initData.environment.workspaceStorageHome = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.workspaceStorageHome));
- - initData.nlsBaseUrl = URI.revive(rpcProtocol.transformIncomingURIs(initData.nlsBaseUrl));
- - initData.logsLocation = URI.revive(rpcProtocol.transformIncomingURIs(initData.logsLocation));
- - initData.workspace = rpcProtocol.transformIncomingURIs(initData.workspace);
- - return initData;
- + initData.environment.extensionTestsLocationURI = URI.revive(
- + rpcProtocol.transformIncomingURIs(initData.environment.extensionTestsLocationURI),
- + )
- + initData.environment.globalStorageHome = URI.revive(
- + rpcProtocol.transformIncomingURIs(initData.environment.globalStorageHome),
- + )
- + initData.environment.workspaceStorageHome = URI.revive(
- + rpcProtocol.transformIncomingURIs(initData.environment.workspaceStorageHome),
- + )
- + initData.nlsBaseUrl = URI.revive(rpcProtocol.transformIncomingURIs(initData.nlsBaseUrl))
- + initData.logsLocation = URI.revive(rpcProtocol.transformIncomingURIs(initData.logsLocation))
- + initData.workspace = rpcProtocol.transformIncomingURIs(initData.workspace)
- + return initData
- }
- }
- diff --git a/src/vs/workbench/api/node/extHostConsoleForwarder.ts b/src/vs/workbench/api/node/extHostConsoleForwarder.ts
- index aa2dbca286c..d9eb33a7043 100644
- --- a/src/vs/workbench/api/node/extHostConsoleForwarder.ts
- +++ b/src/vs/workbench/api/node/extHostConsoleForwarder.ts
- @@ -47,7 +47,7 @@ export class ExtHostConsoleForwarder extends AbstractExtHostConsoleForwarder {
-
- Object.defineProperty(stream, 'write', {
- set: () => { },
- - get: () => (chunk: Uint8Array | string, encoding?: BufferEncoding, callback?: (err?: Error) => void) => {
- + get: () => (chunk: Uint8Array | string, encoding?: BufferEncoding, callback?: (err?: Error | null) => void) => {
- if (!this._isMakingConsoleCall) {
- buf += (chunk as any).toString(encoding);
- const eol = buf.length > MAX_STREAM_BUFFER_LENGTH ? buf.length : buf.lastIndexOf('\n');
- diff --git a/src/vs/workbench/api/node/extensionHostProcess.ts b/src/vs/workbench/api/node/extensionHostProcess.ts
- index 704a0dbb5bd..aa61052558e 100644
- --- a/src/vs/workbench/api/node/extensionHostProcess.ts
- +++ b/src/vs/workbench/api/node/extensionHostProcess.ts
- @@ -29,6 +29,8 @@ import { IDisposable } from '../../../base/common/lifecycle.js';
- import '../common/extHost.common.services.js';
- import './extHost.node.services.js';
- import { createRequire } from 'node:module';
- +import { fileLoggerGlobal } from '../../../../../../src/extension.js';
- +import { RequestInitiator } from '../../services/extensions/common/rpcProtocol.js';
- const require = createRequire(import.meta.url);
-
- interface ParsedExtHostArgs {
- @@ -186,6 +188,7 @@ function _createExtHostProtocol(): Promise<IMessagePassingProtocol> {
- socket = new WebSocketNodeSocket(new NodeSocket(handle, 'extHost-socket'), msg.permessageDeflate, inflateBytes, false);
- }
- if (protocol) {
- + fileLoggerGlobal.logOutgoing(0, 0, RequestInitiator.LocalSide, 'Reconnection case');
- // reconnection case
- disconnectRunner1.cancel();
- disconnectRunner2.cancel();
- @@ -193,6 +196,7 @@ function _createExtHostProtocol(): Promise<IMessagePassingProtocol> {
- protocol.endAcceptReconnection();
- protocol.sendResume();
- } else {
- + fileLoggerGlobal.logOutgoing(0, 0, RequestInitiator.LocalSide, 'New connection case');
- clearTimeout(timer);
- protocol = new PersistentProtocol({ socket, initialChunk: initialDataChunk });
- protocol.sendResume();
- @@ -207,6 +211,7 @@ function _createExtHostProtocol(): Promise<IMessagePassingProtocol> {
- }
- }
- if (msg && msg.type === 'VSCODE_EXTHOST_IPC_REDUCE_GRACE_TIME') {
- + fileLoggerGlobal.logOutgoing(0, 0, RequestInitiator.LocalSide, 'Reduce grace time case');
- if (disconnectRunner2.isScheduled()) {
- // we are disconnected and already running the short reconnection timer
- return;
- @@ -338,12 +343,14 @@ function connectToRenderer(protocol: IMessagePassingProtocol): Promise<IRenderer
- }
-
- // Tell the outside that we are initialized
- + console.log('send initialized message');
- protocol.send(createMessageOfType(MessageType.Initialized));
-
- c({ protocol, initData });
- });
-
- // Tell the outside that we are ready to receive messages
- + console.log('send ready message');
- protocol.send(createMessageOfType(MessageType.Ready));
- });
- }
- @@ -426,4 +433,8 @@ async function startExtensionHostProcess(): Promise<void> {
- onTerminate = (reason: string) => extensionHostMain.terminate(reason);
- }
-
- -startExtensionHostProcess().catch((err) => console.log(err));
- +function start() {
- + startExtensionHostProcess().catch((err) => console.log(err));
- +}
- +
- +export default start;
- \ No newline at end of file
- diff --git a/src/vs/workbench/contrib/webview/common/webview.ts b/src/vs/workbench/contrib/webview/common/webview.ts
- index 95c65048fcd..31aaea4a722 100644
- --- a/src/vs/workbench/contrib/webview/common/webview.ts
- +++ b/src/vs/workbench/contrib/webview/common/webview.ts
- @@ -22,7 +22,7 @@ export const webviewResourceBaseHost = 'vscode-cdn.net';
-
- export const webviewRootResourceAuthority = `vscode-resource.${webviewResourceBaseHost}`;
-
- -export const webviewGenericCspSource = `'self' https://*.${webviewResourceBaseHost}`;
- +export const webviewGenericCspSource = `'self' https://*.${webviewResourceBaseHost} vscode-file://*`;
-
- /**
- * Construct a uri that can load resources inside a webview
- @@ -42,6 +42,15 @@ export function asWebviewUri(resource: URI, remoteInfo?: WebviewRemoteInfo): URI
- return resource;
- }
-
- + if (resource.scheme === Schemas.file) {
- + return URI.from({
- + scheme: "vscode-file",
- + path: resource.path,
- + fragment: resource.fragment,
- + query: resource.query,
- + });
- + }
- +
- if (remoteInfo && remoteInfo.authority && remoteInfo.isRemote && resource.scheme === Schemas.file) {
- resource = URI.from({
- scheme: Schemas.vscodeRemote,
- diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts
- index 382683f3cf7..4478914fdc6 100644
- --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts
- +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts
- @@ -813,6 +813,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx
- const disposableStore = new DisposableStore();
- disposableStore.add(processManager.onDidExit(([code, signal]) => this._onExtensionHostCrashOrExit(processManager, code, signal)));
- disposableStore.add(processManager.onDidChangeResponsiveState((responsiveState) => {
- + console.log(`Extension host (${processManager.friendyName}) is ${responsiveState === ResponsiveState.Responsive ? 'responsive' : 'unresponsive'}.`);
- this._logService.info(`Extension host (${processManager.friendyName}) is ${responsiveState === ResponsiveState.Responsive ? 'responsive' : 'unresponsive'}.`);
- this._onDidChangeResponsiveChange.fire({
- extensionHostKind: processManager.kind,
- diff --git a/src/vs/workbench/services/extensions/common/fileRPCProtocolLogger.ts b/src/vs/workbench/services/extensions/common/fileRPCProtocolLogger.ts
- new file mode 100644
- index 00000000000..1b4fc52e001
- --- /dev/null
- +++ b/src/vs/workbench/services/extensions/common/fileRPCProtocolLogger.ts
- @@ -0,0 +1,246 @@
- +/*---------------------------------------------------------------------------------------------
- + * Copyright (c) Microsoft Corporation. All rights reserved.
- + * Licensed under the MIT License. See License.txt in the project root for license information.
- + *--------------------------------------------------------------------------------------------*/
- +
- +import * as fs from "fs"
- +import * as path from "path"
- +import * as os from "os"
- +import { IRPCProtocolLogger, RequestInitiator } from "./rpcProtocol.js"
- +
- +/**
- + * 文件RPC协议日志记录器,将RPC通信日志保存到文件中
- + */
- +export class FileRPCProtocolLogger implements IRPCProtocolLogger {
- + private _totalIncoming = 0
- + private _totalOutgoing = 0
- + private _logDir: string | undefined
- + private _logFile: string | undefined
- + private _writeStream: fs.WriteStream | null = null
- + private _logQueue: string[] = []
- + private _isInitialized = false
- + private _isDisposed = false
- + private _processInterval: NodeJS.Timeout | null = null
- + private _isEnabled = false
- +
- + constructor(suffix?: string) {
- + if(!this._isEnabled) {
- + return
- + }
- + this._logDir = path.join(os.homedir(), ".ext_host", "log")
- + this._ensureLogDirectoryExists()
- +
- + // 创建日志文件名,使用时间戳确保唯一性
- + const timestamp = new Date().toISOString().replace(/[:.]/g, "-").replace("T", "_").slice(0, 19)
- +
- + // 如果提供了后缀,在文件名中添加
- + const suffixPart = suffix ? `_${suffix}` : '';
- + this._logFile = path.join(this._logDir, `rpc${suffixPart}_${timestamp}.log`)
- +
- + try {
- + // 创建日志文件写入流
- + this._writeStream = fs.createWriteStream(this._logFile, { flags: "a" })
- +
- + // 生成精确到毫秒的时间戳
- + const now = new Date()
- + const startTime = this._formatTimestampWithMilliseconds(now)
- +
- + // 写入日志头
- + const header = [
- + "-------------------------------------------------------------",
- + "Extension Host RPC Protocol Logger",
- + `Started at: ${startTime}`,
- + `Log file: ${this._logFile}`,
- + "-------------------------------------------------------------",
- + ""
- + ].join("\n")
- +
- + this._logQueue.push(header)
- +
- + // 启动日志处理定时器
- + this._startProcessingQueue()
- +
- + this._isInitialized = true
- + console.log(`FileRPCProtocolLogger initialized, log file: ${this._logFile}`)
- + } catch (e) {
- + console.error("Failed to initialize FileRPCProtocolLogger", e)
- + }
- + }
- +
- + /**
- + * 确保日志目录存在
- + */
- + private _ensureLogDirectoryExists(): void {
- + if(!this._logDir) {
- + return
- + }
- + try {
- + if (!fs.existsSync(this._logDir)) {
- + fs.mkdirSync(this._logDir, { recursive: true })
- + }
- + } catch (e) {
- + console.error("Failed to create log directory", e)
- + }
- + }
- +
- + /**
- + * 启动队列处理定时器
- + */
- + private _startProcessingQueue(): void {
- + this._processInterval = setInterval(() => {
- + this._processQueue()
- + }, 100) // 100毫秒处理一次队列
- + }
- +
- + /**
- + * 处理日志队列
- + */
- + private _processQueue(): void {
- + if (this._isDisposed || !this._writeStream || this._logQueue.length === 0) {
- + return
- + }
- +
- + try {
- + // 批量写入日志条目
- + const entries = this._logQueue.splice(0, Math.min(50, this._logQueue.length))
- + for (const entry of entries) {
- + this._writeStream.write(entry + "\n")
- + }
- + } catch (e) {
- + console.error("Failed to write log entries", e)
- + }
- + }
- +
- + /**
- + * 记录传入消息日志
- + */
- + logIncoming(msgLength: number, req: number, initiator: RequestInitiator, str: string, data?: any): void {
- + if (!this._isInitialized) {
- + return
- + }
- +
- + this._totalIncoming += msgLength
- + this._logMessage("IDEA → Ext", this._totalIncoming, msgLength, req, initiator, str, data)
- + }
- +
- + /**
- + * 记录传出消息日志
- + */
- + logOutgoing(msgLength: number, req: number, initiator: RequestInitiator, str: string, data?: any): void {
- + if (!this._isInitialized) {
- + return
- + }
- +
- + this._totalOutgoing += msgLength
- + this._logMessage("Ext → IDEA", this._totalOutgoing, msgLength, req, initiator, str, data)
- + }
- +
- + /**
- + * 记录消息
- + */
- + private _logMessage(
- + direction: string,
- + totalLength: number,
- + msgLength: number,
- + req: number,
- + initiator: RequestInitiator,
- + str: string,
- + data: any
- + ): void {
- + try {
- + const now = new Date()
- + const timestamp = this._formatTimestampWithMilliseconds(now)
- +
- + const initiatorStr = initiator === RequestInitiator.LocalSide ? "Local" : "Other"
- +
- + let logEntry = `[${timestamp}] `
- + logEntry += `[${direction}] `
- + logEntry += `[Total: ${String(totalLength).padStart(7)}] `
- + logEntry += `[Len: ${String(msgLength).padStart(5)}] `
- + logEntry += `[${String(req).padStart(5)}] `
- + logEntry += `[${initiatorStr}] `
- + logEntry += str
- +
- + if (data !== undefined) {
- + const dataStr = /\($/.test(str) ? `${this._stringify(data)})` : this._stringify(data)
- + logEntry += ` ${dataStr}`
- + }
- +
- + this._logQueue.push(logEntry)
- + } catch (e) {
- + console.error("Failed to format log message", e)
- + }
- + }
- +
- + /**
- + * 安全地将数据转换为字符串
- + */
- + private _stringify(data: any): string {
- + try {
- + return JSON.stringify(data, null, 0)
- + } catch (e) {
- + return String(data)
- + }
- + }
- +
- + /**
- + * 释放资源
- + */
- + dispose(): void {
- + if (this._isDisposed) {
- + return
- + }
- +
- + this._isDisposed = true
- +
- + try {
- + // 清除定时器
- + if (this._processInterval) {
- + clearInterval(this._processInterval)
- + this._processInterval = null
- + }
- +
- + // 处理剩余的队列条目
- + this._processQueue()
- +
- + // 生成精确到毫秒的时间戳
- + const now = new Date()
- + const endTime = this._formatTimestampWithMilliseconds(now)
- +
- + // 写入日志尾
- + const footer = [
- + "-------------------------------------------------------------",
- + "Extension Host RPC Protocol Logger",
- + `Ended at: ${endTime}`,
- + `Total incoming: ${this._totalIncoming} bytes`,
- + `Total outgoing: ${this._totalOutgoing} bytes`,
- + "-------------------------------------------------------------"
- + ].join("\n")
- +
- + // 直接写入,不经过队列
- + if (this._writeStream) {
- + this._writeStream.write(footer + "\n")
- + this._writeStream.end()
- + this._writeStream = null
- + }
- +
- + console.log("FileRPCProtocolLogger disposed")
- + } catch (e) {
- + console.error("Failed to dispose FileRPCProtocolLogger", e)
- + }
- + }
- +
- + /**
- + * 格式化时间戳为毫秒级别
- + */
- + private _formatTimestampWithMilliseconds(date: Date): string {
- + const year = date.getFullYear()
- + const month = String(date.getMonth() + 1).padStart(2, '0')
- + const day = String(date.getDate()).padStart(2, '0')
- + const hours = String(date.getHours()).padStart(2, '0')
- + const minutes = String(date.getMinutes()).padStart(2, '0')
- + const seconds = String(date.getSeconds()).padStart(2, '0')
- + const milliseconds = String(date.getMilliseconds()).padStart(3, '0')
- + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${milliseconds}`
- + }
- +}
- \ No newline at end of file
- diff --git a/src/vs/workbench/services/extensions/common/rpcProtocol.ts b/src/vs/workbench/services/extensions/common/rpcProtocol.ts
- index 6467e585843..eeb99f77f4a 100644
- --- a/src/vs/workbench/services/extensions/common/rpcProtocol.ts
- +++ b/src/vs/workbench/services/extensions/common/rpcProtocol.ts
- @@ -288,6 +288,7 @@ export class RPCProtocol extends Disposable implements IRPCProtocol {
- const buff = MessageBuffer.read(rawmsg, 0);
- const messageType = <MessageType>buff.readUInt8();
- const req = buff.readUInt32();
- + this._logger?.logIncoming(msgLength, req, RequestInitiator.OtherSide, `receiveMessage: ${messageType}, req: ${req}, msgType: ${messageType}`);
-
- switch (messageType) {
- case MessageType.RequestJSONArgs:
- @@ -309,7 +310,7 @@ export class RPCProtocol extends Disposable implements IRPCProtocol {
- break;
- }
- case MessageType.Acknowledged: {
- - this._logger?.logIncoming(msgLength, req, RequestInitiator.LocalSide, `ack`);
- + // this._logger?.logIncoming(msgLength, req, RequestInitiator.LocalSide, `ack`);
- this._onDidReceiveAcknowledge(req);
- break;
- }
- @@ -442,6 +443,7 @@ export class RPCProtocol extends Disposable implements IRPCProtocol {
- try {
- return Promise.resolve(this._doInvokeHandler(rpcId, methodName, args));
- } catch (err) {
- + console.error('invokeHandler error:', err);
- return Promise.reject(err);
- }
- }
|