AbstractOperations.cpp 243 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380
  1. /*
  2. * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
  3. * Copyright (c) 2023, Matthew Olsson <mattco@serenityos.org>
  4. * Copyright (c) 2023-2024, Shannon Booth <shannon@serenityos.org>
  5. * Copyright (c) 2023-2024, Kenneth Myhra <kennethmyhra@serenityos.org>
  6. *
  7. * SPDX-License-Identifier: BSD-2-Clause
  8. */
  9. #include <LibJS/Runtime/Array.h>
  10. #include <LibJS/Runtime/ArrayBuffer.h>
  11. #include <LibJS/Runtime/DataView.h>
  12. #include <LibJS/Runtime/DataViewConstructor.h>
  13. #include <LibJS/Runtime/Intrinsics.h>
  14. #include <LibJS/Runtime/Iterator.h>
  15. #include <LibJS/Runtime/PromiseCapability.h>
  16. #include <LibJS/Runtime/PromiseConstructor.h>
  17. #include <LibJS/Runtime/TypedArray.h>
  18. #include <LibWeb/Bindings/ExceptionOrUtils.h>
  19. #include <LibWeb/DOM/AbortSignal.h>
  20. #include <LibWeb/HTML/EventLoop/EventLoop.h>
  21. #include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
  22. #include <LibWeb/HTML/StructuredSerialize.h>
  23. #include <LibWeb/Streams/AbstractOperations.h>
  24. #include <LibWeb/Streams/QueuingStrategy.h>
  25. #include <LibWeb/Streams/ReadableByteStreamController.h>
  26. #include <LibWeb/Streams/ReadableStream.h>
  27. #include <LibWeb/Streams/ReadableStreamBYOBReader.h>
  28. #include <LibWeb/Streams/ReadableStreamBYOBRequest.h>
  29. #include <LibWeb/Streams/ReadableStreamDefaultController.h>
  30. #include <LibWeb/Streams/ReadableStreamDefaultReader.h>
  31. #include <LibWeb/Streams/ReadableStreamGenericReader.h>
  32. #include <LibWeb/Streams/TransformStream.h>
  33. #include <LibWeb/Streams/TransformStreamDefaultController.h>
  34. #include <LibWeb/Streams/Transformer.h>
  35. #include <LibWeb/Streams/UnderlyingSink.h>
  36. #include <LibWeb/Streams/UnderlyingSource.h>
  37. #include <LibWeb/Streams/WritableStream.h>
  38. #include <LibWeb/Streams/WritableStreamDefaultController.h>
  39. #include <LibWeb/Streams/WritableStreamDefaultWriter.h>
  40. #include <LibWeb/WebIDL/AbstractOperations.h>
  41. #include <LibWeb/WebIDL/Buffers.h>
  42. #include <LibWeb/WebIDL/ExceptionOr.h>
  43. #include <LibWeb/WebIDL/Promise.h>
  44. namespace Web::Streams {
  45. // https://streams.spec.whatwg.org/#close-sentinel
  46. // Non-standard function that implements the "close sentinel" value.
  47. static JS::Value create_close_sentinel()
  48. {
  49. // The close sentinel is a unique value enqueued into [[queue]], in lieu of a chunk, to signal that the stream is closed. It is only used internally, and is never exposed to web developers.
  50. // Note: We use the empty Value to signal this as, similarly to the note above, the empty value is not exposed to nor creatable by web developers.
  51. return {};
  52. }
  53. // https://streams.spec.whatwg.org/#close-sentinel
  54. // Non-standard function that implements the "If value is a close sentinel" check.
  55. static bool is_close_sentinel(JS::Value value)
  56. {
  57. return value.is_empty();
  58. }
  59. // NON-STANDARD: Can be used instead of CreateReadableStream in cases where we need to set up a newly allocated
  60. // ReadableStream before initialization of said ReadableStream, i.e. ReadableStream is captured by lambdas in an uninitialized state.
  61. // Spec steps are taken from: https://streams.spec.whatwg.org/#create-readable-stream
  62. static WebIDL::ExceptionOr<void> set_up_readable_stream(JS::Realm& realm, ReadableStream& stream, GC::Ref<StartAlgorithm> start_algorithm, GC::Ref<PullAlgorithm> pull_algorithm, GC::Ref<CancelAlgorithm> cancel_algorithm, Optional<double> high_water_mark = {}, GC::Ptr<SizeAlgorithm> size_algorithm = {})
  63. {
  64. // 1. If highWaterMark was not passed, set it to 1.
  65. if (!high_water_mark.has_value())
  66. high_water_mark = 1.0;
  67. // 2. If sizeAlgorithm was not passed, set it to an algorithm that returns 1.
  68. if (!size_algorithm)
  69. size_algorithm = GC::create_function(realm.heap(), [](JS::Value) { return JS::normal_completion(JS::Value(1)); });
  70. // 3. Assert: ! IsNonNegativeNumber(highWaterMark) is true.
  71. VERIFY(is_non_negative_number(JS::Value { *high_water_mark }));
  72. // 4. Let stream be a new ReadableStream.
  73. // NOTE: The ReadableStream is allocated outside the scope of this method.
  74. // 5. Perform ! InitializeReadableStream(stream).
  75. initialize_readable_stream(stream);
  76. // 6. Let controller be a new ReadableStreamDefaultController.
  77. auto controller = realm.create<ReadableStreamDefaultController>(realm);
  78. // 7. Perform ? SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm).
  79. TRY(set_up_readable_stream_default_controller(stream, *controller, start_algorithm, pull_algorithm, cancel_algorithm, *high_water_mark, *size_algorithm));
  80. return {};
  81. }
  82. // https://streams.spec.whatwg.org/#acquire-readable-stream-reader
  83. WebIDL::ExceptionOr<GC::Ref<ReadableStreamDefaultReader>> acquire_readable_stream_default_reader(ReadableStream& stream)
  84. {
  85. auto& realm = stream.realm();
  86. // 1. Let reader be a new ReadableStreamDefaultReader.
  87. auto reader = realm.create<ReadableStreamDefaultReader>(realm);
  88. // 2. Perform ? SetUpReadableStreamDefaultReader(reader, stream).
  89. TRY(set_up_readable_stream_default_reader(reader, stream));
  90. // 3. Return reader.
  91. return reader;
  92. }
  93. // https://streams.spec.whatwg.org/#acquire-readable-stream-byob-reader
  94. WebIDL::ExceptionOr<GC::Ref<ReadableStreamBYOBReader>> acquire_readable_stream_byob_reader(ReadableStream& stream)
  95. {
  96. auto& realm = stream.realm();
  97. // 1. Let reader be a new ReadableStreamBYOBReader.
  98. auto reader = realm.create<ReadableStreamBYOBReader>(realm);
  99. // 2. Perform ? SetUpReadableStreamBYOBReader(reader, stream).
  100. TRY(set_up_readable_stream_byob_reader(reader, stream));
  101. // 3. Return reader.
  102. return reader;
  103. }
  104. // https://streams.spec.whatwg.org/#is-readable-stream-locked
  105. bool is_readable_stream_locked(ReadableStream const& stream)
  106. {
  107. // 1. If stream.[[reader]] is undefined, return false.
  108. if (!stream.reader().has_value())
  109. return false;
  110. // 2. Return true.
  111. return true;
  112. }
  113. // https://streams.spec.whatwg.org/#readable-stream-cancel
  114. GC::Ref<WebIDL::Promise> readable_stream_cancel(ReadableStream& stream, JS::Value reason)
  115. {
  116. auto& realm = stream.realm();
  117. // 1. Set stream.[[disturbed]] to true.
  118. stream.set_disturbed(true);
  119. // 2. If stream.[[state]] is "closed", return a promise resolved with undefined.
  120. if (stream.state() == ReadableStream::State::Closed)
  121. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  122. // 3. If stream.[[state]] is "errored", return a promise rejected with stream.[[storedError]].
  123. if (stream.state() == ReadableStream::State::Errored)
  124. return WebIDL::create_rejected_promise(realm, stream.stored_error());
  125. // 4. Perform ! ReadableStreamClose(stream).
  126. readable_stream_close(stream);
  127. // 5. Let reader be stream.[[reader]].
  128. auto reader = stream.reader();
  129. // 6. If reader is not undefined and reader implements ReadableStreamBYOBReader,
  130. if (reader.has_value() && reader->has<GC::Ref<ReadableStreamBYOBReader>>()) {
  131. // 1. Let readIntoRequests be reader.[[readIntoRequests]].
  132. // 2. Set reader.[[readIntoRequests]] to an empty list.
  133. auto read_into_requests = move(reader->get<GC::Ref<ReadableStreamBYOBReader>>()->read_into_requests());
  134. // 3. For each readIntoRequest of readIntoRequests,
  135. for (auto& read_into_request : read_into_requests) {
  136. // 1. Perform readIntoRequest’s close steps, given undefined.
  137. read_into_request->on_close(JS::js_undefined());
  138. }
  139. }
  140. // 7. Let sourceCancelPromise be ! stream.[[controller]].[[CancelSteps]](reason).
  141. auto source_cancel_promise = stream.controller()->visit([&](auto const& controller) {
  142. return controller->cancel_steps(reason);
  143. });
  144. // 8. Return the result of reacting to sourceCancelPromise with a fulfillment step that returns undefined.
  145. auto react_result = WebIDL::react_to_promise(*source_cancel_promise,
  146. GC::create_function(stream.heap(), [](JS::Value) -> WebIDL::ExceptionOr<JS::Value> { return JS::js_undefined(); }),
  147. {});
  148. return react_result;
  149. }
  150. // https://streams.spec.whatwg.org/#readable-stream-fulfill-read-into-request
  151. void readable_stream_fulfill_read_into_request(ReadableStream& stream, JS::Value chunk, bool done)
  152. {
  153. // 1. Assert: ! ReadableStreamHasBYOBReader(stream) is true.
  154. VERIFY(readable_stream_has_byob_reader(stream));
  155. // 2. Let reader be stream.[[reader]].
  156. auto reader = stream.reader()->get<GC::Ref<ReadableStreamBYOBReader>>();
  157. // 3. Assert: reader.[[readIntoRequests]] is not empty.
  158. VERIFY(!reader->read_into_requests().is_empty());
  159. // 4. Let readIntoRequest be reader.[[readIntoRequests]][0].
  160. // 5. Remove readIntoRequest from reader.[[readIntoRequests]].
  161. auto read_into_request = reader->read_into_requests().take_first();
  162. // 6. If done is true, perform readIntoRequest’s close steps, given chunk.
  163. if (done) {
  164. read_into_request->on_close(chunk);
  165. }
  166. // 7. Otherwise, perform readIntoRequest’s chunk steps, given chunk.
  167. else {
  168. read_into_request->on_chunk(chunk);
  169. }
  170. }
  171. // https://streams.spec.whatwg.org/#readable-stream-fulfill-read-request
  172. void readable_stream_fulfill_read_request(ReadableStream& stream, JS::Value chunk, bool done)
  173. {
  174. // 1. Assert: ! ReadableStreamHasDefaultReader(stream) is true.
  175. VERIFY(readable_stream_has_default_reader(stream));
  176. // 2. Let reader be stream.[[reader]].
  177. auto reader = stream.reader()->get<GC::Ref<ReadableStreamDefaultReader>>();
  178. // 3. Assert: reader.[[readRequests]] is not empty.
  179. VERIFY(!reader->read_requests().is_empty());
  180. // 4. Let readRequest be reader.[[readRequests]][0].
  181. // 5. Remove readRequest from reader.[[readRequests]].
  182. auto read_request = reader->read_requests().take_first();
  183. // 6. If done is true, perform readRequest’s close steps.
  184. if (done) {
  185. read_request->on_close();
  186. }
  187. // 7. Otherwise, perform readRequest’s chunk steps, given chunk.
  188. else {
  189. read_request->on_chunk(chunk);
  190. }
  191. }
  192. // https://streams.spec.whatwg.org/#readable-stream-get-num-read-into-requests
  193. size_t readable_stream_get_num_read_into_requests(ReadableStream const& stream)
  194. {
  195. // 1. Assert: ! ReadableStreamHasBYOBReader(stream) is true.
  196. VERIFY(readable_stream_has_byob_reader(stream));
  197. // 2. Return stream.[[reader]].[[readIntoRequests]]'s size.
  198. return stream.reader()->get<GC::Ref<ReadableStreamBYOBReader>>()->read_into_requests().size();
  199. }
  200. // https://streams.spec.whatwg.org/#readable-stream-get-num-read-requests
  201. size_t readable_stream_get_num_read_requests(ReadableStream const& stream)
  202. {
  203. // 1. Assert: ! ReadableStreamHasDefaultReader(stream) is true.
  204. VERIFY(readable_stream_has_default_reader(stream));
  205. // 2. Return stream.[[reader]].[[readRequests]]'s size.
  206. return stream.reader()->get<GC::Ref<ReadableStreamDefaultReader>>()->read_requests().size();
  207. }
  208. // https://streams.spec.whatwg.org/#readable-stream-has-byob-reader
  209. bool readable_stream_has_byob_reader(ReadableStream const& stream)
  210. {
  211. // 1. Let reader be stream.[[reader]].
  212. auto reader = stream.reader();
  213. // 2. If reader is undefined, return false.
  214. if (!reader.has_value())
  215. return false;
  216. // 3. If reader implements ReadableStreamBYOBReader, return true.
  217. if (reader->has<GC::Ref<ReadableStreamBYOBReader>>())
  218. return true;
  219. // 4. Return false.
  220. return false;
  221. }
  222. // https://streams.spec.whatwg.org/#readable-stream-has-default-reader
  223. bool readable_stream_has_default_reader(ReadableStream const& stream)
  224. {
  225. // 1. Let reader be stream.[[reader]].
  226. auto reader = stream.reader();
  227. // 2. If reader is undefined, return false.
  228. if (!reader.has_value())
  229. return false;
  230. // 3. If reader implements ReadableStreamDefaultReader, return true.
  231. if (reader->has<GC::Ref<ReadableStreamDefaultReader>>())
  232. return true;
  233. // 4. Return false.
  234. return false;
  235. }
  236. // https://streams.spec.whatwg.org/#readable-stream-pipe-to
  237. GC::Ref<WebIDL::Promise> readable_stream_pipe_to(ReadableStream& source, WritableStream& dest, bool, bool, bool, Optional<JS::Value> signal)
  238. {
  239. auto& realm = source.realm();
  240. // 1. Assert: source implements ReadableStream.
  241. // 2. Assert: dest implements WritableStream.
  242. // 3. Assert: preventClose, preventAbort, and preventCancel are all booleans.
  243. // 4. If signal was not given, let signal be undefined.
  244. if (!signal.has_value())
  245. signal = JS::js_undefined();
  246. // 5. Assert: either signal is undefined, or signal implements AbortSignal.
  247. VERIFY(signal->is_undefined() || (signal->is_object() && is<DOM::AbortSignal>(signal->as_object())));
  248. // 6. Assert: ! IsReadableStreamLocked(source) is false.
  249. VERIFY(!is_readable_stream_locked(source));
  250. // 7. Assert: ! IsWritableStreamLocked(dest) is false.
  251. VERIFY(!is_writable_stream_locked(dest));
  252. // 8. If source.[[controller]] implements ReadableByteStreamController, let reader be either ! AcquireReadableStreamBYOBReader(source)
  253. // or ! AcquireReadableStreamDefaultReader(source), at the user agent’s discretion.
  254. // 9. Otherwise, let reader be ! AcquireReadableStreamDefaultReader(source).
  255. auto reader = MUST(source.controller()->visit(
  256. [](auto const& controller) {
  257. return acquire_readable_stream_default_reader(*controller->stream());
  258. }));
  259. // 10. Let writer be ! AcquireWritableStreamDefaultWriter(dest).
  260. auto writer = MUST(acquire_writable_stream_default_writer(dest));
  261. // 11. Set source.[[disturbed]] to true.
  262. source.set_disturbed(true);
  263. // FIXME: 12. Let shuttingDown be false.
  264. // 13. Let promise be a new promise.
  265. auto promise = WebIDL::create_promise(realm);
  266. // FIXME 14. If signal is not undefined,
  267. // 1. Let abortAlgorithm be the following steps:
  268. // 1. Let error be signal’s abort reason.
  269. // 2. Let actions be an empty ordered set.
  270. // 3. If preventAbort is false, append the following action to actions:
  271. // 1. If dest.[[state]] is "writable", return ! WritableStreamAbort(dest, error).
  272. // 2. Otherwise, return a promise resolved with undefined.
  273. // 4. If preventCancel is false, append the following action to actions:
  274. // 1. If source.[[state]] is "readable", return ! ReadableStreamCancel(source, error).
  275. // 2. Otherwise, return a promise resolved with undefined.
  276. // 5. Shutdown with an action consisting of getting a promise to wait for all of the actions in actions, and with error.
  277. // 2. If signal is aborted, perform abortAlgorithm and return promise.
  278. // 3. Add abortAlgorithm to signal.
  279. // 15. In parallel but not really; see #905, using reader and writer, read all chunks from source and write them to
  280. // dest. Due to the locking provided by the reader and writer, the exact manner in which this happens is not
  281. // observable to author code, and so there is flexibility in how this is done. The following constraints apply
  282. // regardless of the exact algorithm used:
  283. // - Public API must not be used: while reading or writing, or performing any of the operations below, the
  284. // JavaScript-modifiable reader, writer, and stream APIs (i.e. methods on the appropriate prototypes) must not
  285. // be used. Instead, the streams must be manipulated directly.
  286. // FIXME: Currently a naive implementation that uses ReadableStreamDefaultReader::read_all_chunks() to read all chunks
  287. // from the source and then through the callback success_steps writes those chunks to the destination.
  288. auto chunk_steps = GC::create_function(realm.heap(), [&realm, writer](ByteBuffer buffer) {
  289. auto array_buffer = JS::ArrayBuffer::create(realm, move(buffer));
  290. auto chunk = JS::Uint8Array::create(realm, array_buffer->byte_length(), *array_buffer);
  291. auto promise = writable_stream_default_writer_write(writer, chunk);
  292. WebIDL::resolve_promise(realm, promise, JS::js_undefined());
  293. });
  294. auto success_steps = GC::create_function(realm.heap(), [promise, &realm, reader, writer](ByteBuffer) {
  295. // Make sure we close the acquired writer.
  296. WebIDL::resolve_promise(realm, writable_stream_default_writer_close(*writer), JS::js_undefined());
  297. readable_stream_default_reader_release(*reader);
  298. WebIDL::resolve_promise(realm, promise, JS::js_undefined());
  299. });
  300. auto failure_steps = GC::create_function(realm.heap(), [promise, &realm, reader, writer](JS::Value error) {
  301. // Make sure we close the acquired writer.
  302. WebIDL::resolve_promise(realm, writable_stream_default_writer_close(*writer), JS::js_undefined());
  303. readable_stream_default_reader_release(*reader);
  304. WebIDL::reject_promise(realm, promise, error);
  305. });
  306. reader->read_all_chunks(chunk_steps, success_steps, failure_steps);
  307. // 16. Return promise.
  308. return promise;
  309. }
  310. // https://streams.spec.whatwg.org/#readable-stream-tee
  311. WebIDL::ExceptionOr<ReadableStreamPair> readable_stream_tee(JS::Realm& realm, ReadableStream& stream, bool clone_for_branch2)
  312. {
  313. // 1. Assert: stream implements ReadableStream.
  314. // 2. Assert: cloneForBranch2 is a boolean.
  315. // 3. If stream.[[controller]] implements ReadableByteStreamController, return ? ReadableByteStreamTee(stream).
  316. if (stream.controller()->has<GC::Ref<Streams::ReadableByteStreamController>>()) {
  317. return TRY(readable_byte_stream_tee(realm, stream));
  318. }
  319. // 4. Return ? ReadableStreamDefaultTee(stream, cloneForBranch2).
  320. return TRY(readable_stream_default_tee(realm, stream, clone_for_branch2));
  321. }
  322. struct DefaultStreamTeeParams final : JS::Cell {
  323. GC_CELL(DefaultStreamTeeParams, JS::Cell);
  324. GC_DECLARE_ALLOCATOR(DefaultStreamTeeParams);
  325. virtual void visit_edges(Visitor& visitor) override
  326. {
  327. Base::visit_edges(visitor);
  328. visitor.visit(reason1);
  329. visitor.visit(reason2);
  330. visitor.visit(branch1);
  331. visitor.visit(branch2);
  332. visitor.visit(pull_algorithm);
  333. }
  334. bool reading { false };
  335. bool read_again { false };
  336. bool canceled1 { false };
  337. bool canceled2 { false };
  338. JS::Value reason1 { JS::js_undefined() };
  339. JS::Value reason2 { JS::js_undefined() };
  340. GC::Ptr<ReadableStream> branch1;
  341. GC::Ptr<ReadableStream> branch2;
  342. GC::Ptr<PullAlgorithm> pull_algorithm;
  343. };
  344. GC_DEFINE_ALLOCATOR(DefaultStreamTeeParams);
  345. // https://streams.spec.whatwg.org/#ref-for-read-request③
  346. class DefaultStreamTeeReadRequest final : public ReadRequest {
  347. GC_CELL(DefaultStreamTeeReadRequest, ReadRequest);
  348. GC_DECLARE_ALLOCATOR(DefaultStreamTeeReadRequest);
  349. public:
  350. DefaultStreamTeeReadRequest(
  351. JS::Realm& realm,
  352. GC::Ref<ReadableStream> stream,
  353. GC::Ref<DefaultStreamTeeParams> params,
  354. GC::Ref<WebIDL::Promise> cancel_promise,
  355. bool clone_for_branch2)
  356. : m_realm(realm)
  357. , m_stream(stream)
  358. , m_params(params)
  359. , m_cancel_promise(cancel_promise)
  360. , m_clone_for_branch2(clone_for_branch2)
  361. {
  362. }
  363. // https://streams.spec.whatwg.org/#ref-for-read-request-chunk-steps③
  364. virtual void on_chunk(JS::Value chunk) override
  365. {
  366. // 1. Queue a microtask to perform the following steps:
  367. HTML::queue_a_microtask(nullptr, GC::create_function(m_realm->heap(), [this, chunk]() {
  368. HTML::TemporaryExecutionContext execution_context { m_realm, HTML::TemporaryExecutionContext::CallbacksEnabled::Yes };
  369. auto controller1 = m_params->branch1->controller()->get<GC::Ref<ReadableStreamDefaultController>>();
  370. auto controller2 = m_params->branch2->controller()->get<GC::Ref<ReadableStreamDefaultController>>();
  371. // 1. Set readAgain to false.
  372. m_params->read_again = false;
  373. // 2. Let chunk1 and chunk2 be chunk.
  374. auto chunk1 = chunk;
  375. auto chunk2 = chunk;
  376. // 3. If canceled2 is false and cloneForBranch2 is true,
  377. if (!m_params->canceled2 && m_clone_for_branch2) {
  378. // 1. Let cloneResult be StructuredClone(chunk2).
  379. auto clone_result = structured_clone(m_realm, chunk2);
  380. // 2. If cloneResult is an abrupt completion,
  381. if (clone_result.is_exception()) {
  382. auto completion = Bindings::exception_to_throw_completion(m_realm->vm(), clone_result.release_error());
  383. // 1. Perform ! ReadableStreamDefaultControllerError(branch1.[[controller]], cloneResult.[[Value]]).
  384. readable_stream_default_controller_error(controller1, completion.value().value());
  385. // 2. Perform ! ReadableStreamDefaultControllerError(branch2.[[controller]], cloneResult.[[Value]]).
  386. readable_stream_default_controller_error(controller2, completion.value().value());
  387. // 3. Resolve cancelPromise with ! ReadableStreamCancel(stream, cloneResult.[[Value]]).
  388. auto cancel_result = readable_stream_cancel(m_stream, completion.value().value());
  389. // Note: We need to manually convert the result to an ECMAScript value here, by extracting its [[Promise]] slot.
  390. WebIDL::resolve_promise(m_realm, m_cancel_promise, cancel_result->promise());
  391. // 4. Return.
  392. return;
  393. }
  394. // 3. Otherwise, set chunk2 to cloneResult.[[Value]].
  395. chunk2 = clone_result.release_value();
  396. }
  397. // 4. If canceled1 is false, perform ! ReadableStreamDefaultControllerEnqueue(branch1.[[controller]], chunk1).
  398. if (!m_params->canceled1) {
  399. MUST(readable_stream_default_controller_enqueue(controller1, chunk1));
  400. }
  401. // 5. If canceled2 is false, perform ! ReadableStreamDefaultControllerEnqueue(branch2.[[controller]], chunk2).
  402. if (!m_params->canceled2) {
  403. MUST(readable_stream_default_controller_enqueue(controller2, chunk2));
  404. }
  405. // 6. Set reading to false.
  406. m_params->reading = false;
  407. // 7. If readAgain is true, perform pullAlgorithm.
  408. if (m_params->read_again) {
  409. m_params->pull_algorithm->function()();
  410. }
  411. }));
  412. // NOTE: The microtask delay here is necessary because it takes at least a microtask to detect errors, when we
  413. // use reader.[[closedPromise]] below. We want errors in stream to error both branches immediately, so we
  414. // cannot let successful synchronously-available reads happen ahead of asynchronously-available errors.
  415. }
  416. // https://streams.spec.whatwg.org/#ref-for-read-request-close-steps②
  417. virtual void on_close() override
  418. {
  419. auto controller1 = m_params->branch1->controller()->get<GC::Ref<ReadableStreamDefaultController>>();
  420. auto controller2 = m_params->branch2->controller()->get<GC::Ref<ReadableStreamDefaultController>>();
  421. // 1. Set reading to false.
  422. m_params->reading = false;
  423. // 2. If canceled1 is false, perform ! ReadableStreamDefaultControllerClose(branch1.[[controller]]).
  424. if (!m_params->canceled1) {
  425. readable_stream_default_controller_close(controller1);
  426. }
  427. // 3. If canceled2 is false, perform ! ReadableStreamDefaultControllerClose(branch2.[[controller]]).
  428. if (!m_params->canceled2) {
  429. readable_stream_default_controller_close(controller2);
  430. }
  431. // 4. If canceled1 is false or canceled2 is false, resolve cancelPromise with undefined.
  432. if (!m_params->canceled1 || !m_params->canceled2) {
  433. WebIDL::resolve_promise(m_realm, m_cancel_promise, JS::js_undefined());
  434. }
  435. }
  436. // https://streams.spec.whatwg.org/#ref-for-read-request-error-steps③
  437. virtual void on_error(JS::Value) override
  438. {
  439. // 1. Set reading to false.
  440. m_params->reading = false;
  441. }
  442. private:
  443. virtual void visit_edges(Visitor& visitor) override
  444. {
  445. Base::visit_edges(visitor);
  446. visitor.visit(m_realm);
  447. visitor.visit(m_stream);
  448. visitor.visit(m_params);
  449. visitor.visit(m_cancel_promise);
  450. }
  451. GC::Ref<JS::Realm> m_realm;
  452. GC::Ref<ReadableStream> m_stream;
  453. GC::Ref<DefaultStreamTeeParams> m_params;
  454. GC::Ref<WebIDL::Promise> m_cancel_promise;
  455. bool m_clone_for_branch2 { false };
  456. };
  457. GC_DEFINE_ALLOCATOR(DefaultStreamTeeReadRequest);
  458. // https://streams.spec.whatwg.org/#abstract-opdef-readablestreamdefaulttee
  459. WebIDL::ExceptionOr<ReadableStreamPair> readable_stream_default_tee(JS::Realm& realm, ReadableStream& stream, bool clone_for_branch2)
  460. {
  461. // 1. Assert: stream implements ReadableStream.
  462. // 2. Assert: cloneForBranch2 is a boolean.
  463. // 3. Let reader be ? AcquireReadableStreamDefaultReader(stream).
  464. auto reader = TRY(acquire_readable_stream_default_reader(stream));
  465. // 4. Let reading be false.
  466. // 5. Let readAgain be false.
  467. // 6. Let canceled1 be false.
  468. // 7. Let canceled2 be false.
  469. // 8. Let reason1 be undefined.
  470. // 9. Let reason2 be undefined.
  471. // 10. Let branch1 be undefined.
  472. // 11. Let branch2 be undefined.
  473. auto params = realm.create<DefaultStreamTeeParams>();
  474. // 12. Let cancelPromise be a new promise.
  475. auto cancel_promise = WebIDL::create_promise(realm);
  476. // 13. Let pullAlgorithm be the following steps:
  477. auto pull_algorithm = GC::create_function(realm.heap(), [&realm, &stream, reader, params, cancel_promise, clone_for_branch2]() {
  478. // 1. If reading is true,
  479. if (params->reading) {
  480. // 1. Set readAgain to true.
  481. params->read_again = true;
  482. // 2. Return a promise resolved with undefined.
  483. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  484. }
  485. // 2. Set reading to true.
  486. params->reading = true;
  487. // 3. Let readRequest be a read request with the following items:
  488. auto read_request = realm.heap().allocate<DefaultStreamTeeReadRequest>(realm, stream, params, cancel_promise, clone_for_branch2);
  489. // 4. Perform ! ReadableStreamDefaultReaderRead(reader, readRequest).
  490. readable_stream_default_reader_read(reader, read_request);
  491. // 5. Return a promise resolved with undefined.
  492. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  493. });
  494. // AD-HOC: The read request within the pull algorithm must be able to re-invoke the pull algorithm, so cache it here.
  495. params->pull_algorithm = pull_algorithm;
  496. // 14. Let cancel1Algorithm be the following steps, taking a reason argument:
  497. auto cancel1_algorithm = GC::create_function(realm.heap(), [&realm, &stream, params, cancel_promise](JS::Value reason) {
  498. // 1. Set canceled1 to true.
  499. params->canceled1 = true;
  500. // 2. Set reason1 to reason.
  501. params->reason1 = reason;
  502. // 3. If canceled2 is true,
  503. if (params->canceled2) {
  504. // 1. Let compositeReason be ! CreateArrayFromList(« reason1, reason2 »).
  505. auto composite_reason = JS::Array::create_from(realm, AK::Array { params->reason1, params->reason2 });
  506. // 2. Let cancelResult be ! ReadableStreamCancel(stream, compositeReason).
  507. auto cancel_result = readable_stream_cancel(stream, composite_reason);
  508. // 3. Resolve cancelPromise with cancelResult.
  509. WebIDL::resolve_promise(realm, cancel_promise, cancel_result->promise());
  510. }
  511. // 4. Return cancelPromise.
  512. return cancel_promise;
  513. });
  514. // 15. Let cancel2Algorithm be the following steps, taking a reason argument:
  515. auto cancel2_algorithm = GC::create_function(realm.heap(), [&realm, &stream, params, cancel_promise](JS::Value reason) {
  516. // 1. Set canceled2 to true.
  517. params->canceled2 = true;
  518. // 2. Set reason2 to reason.
  519. params->reason2 = reason;
  520. // 3. If canceled1 is true,
  521. if (params->canceled1) {
  522. // 1. Let compositeReason be ! CreateArrayFromList(« reason1, reason2 »).
  523. auto composite_reason = JS::Array::create_from(realm, AK::Array { params->reason1, params->reason2 });
  524. // 2. Let cancelResult be ! ReadableStreamCancel(stream, compositeReason).
  525. auto cancel_result = readable_stream_cancel(stream, composite_reason);
  526. // 3. Resolve cancelPromise with cancelResult.
  527. WebIDL::resolve_promise(realm, cancel_promise, cancel_result->promise());
  528. }
  529. // 4. Return cancelPromise.
  530. return cancel_promise;
  531. });
  532. // 16. Let startAlgorithm be an algorithm that returns undefined.
  533. auto start_algorithm = GC::create_function(realm.heap(), []() -> WebIDL::ExceptionOr<JS::Value> {
  534. return JS::js_undefined();
  535. });
  536. // 17. Set branch1 to ! CreateReadableStream(startAlgorithm, pullAlgorithm, cancel1Algorithm).
  537. params->branch1 = MUST(create_readable_stream(realm, start_algorithm, pull_algorithm, cancel1_algorithm));
  538. // 18. Set branch2 to ! CreateReadableStream(startAlgorithm, pullAlgorithm, cancel2Algorithm).
  539. params->branch2 = MUST(create_readable_stream(realm, start_algorithm, pull_algorithm, cancel2_algorithm));
  540. // 19. Upon rejection of reader.[[closedPromise]] with reason r,
  541. WebIDL::upon_rejection(*reader->closed_promise_capability(), GC::create_function(realm.heap(), [&realm, params, cancel_promise](JS::Value reason) -> WebIDL::ExceptionOr<JS::Value> {
  542. auto controller1 = params->branch1->controller()->get<GC::Ref<ReadableStreamDefaultController>>();
  543. auto controller2 = params->branch2->controller()->get<GC::Ref<ReadableStreamDefaultController>>();
  544. // 1. Perform ! ReadableStreamDefaultControllerError(branch1.[[controller]], r).
  545. readable_stream_default_controller_error(controller1, reason);
  546. // 2. Perform ! ReadableStreamDefaultControllerError(branch2.[[controller]], r).
  547. readable_stream_default_controller_error(controller2, reason);
  548. // 3. If canceled1 is false or canceled2 is false, resolve cancelPromise with undefined.
  549. if (!params->canceled1 || !params->canceled2) {
  550. WebIDL::resolve_promise(realm, cancel_promise, JS::js_undefined());
  551. }
  552. return JS::js_undefined();
  553. }));
  554. // 20. Return « branch1, branch2 ».
  555. return ReadableStreamPair { *params->branch1, *params->branch2 };
  556. }
  557. struct ByteStreamTeeParams final : JS::Cell {
  558. GC_CELL(ByteStreamTeeParams, JS::Cell);
  559. GC_DECLARE_ALLOCATOR(ByteStreamTeeParams);
  560. explicit ByteStreamTeeParams(ReadableStreamReader reader)
  561. : reader(move(reader))
  562. {
  563. }
  564. virtual void visit_edges(Visitor& visitor) override
  565. {
  566. Base::visit_edges(visitor);
  567. visitor.visit(reason1);
  568. visitor.visit(reason2);
  569. visitor.visit(branch1);
  570. visitor.visit(branch2);
  571. visitor.visit(pull1_algorithm);
  572. visitor.visit(pull2_algorithm);
  573. reader.visit([&](auto const& underlying_reader) { visitor.visit(underlying_reader); });
  574. }
  575. bool reading { false };
  576. bool read_again_for_branch1 { false };
  577. bool read_again_for_branch2 { false };
  578. bool canceled1 { false };
  579. bool canceled2 { false };
  580. JS::Value reason1 { JS::js_undefined() };
  581. JS::Value reason2 { JS::js_undefined() };
  582. GC::Ptr<ReadableStream> branch1;
  583. GC::Ptr<ReadableStream> branch2;
  584. GC::Ptr<PullAlgorithm> pull1_algorithm;
  585. GC::Ptr<PullAlgorithm> pull2_algorithm;
  586. ReadableStreamReader reader;
  587. };
  588. GC_DEFINE_ALLOCATOR(ByteStreamTeeParams);
  589. // https://streams.spec.whatwg.org/#ref-for-read-request④
  590. class ByteStreamTeeDefaultReadRequest final : public ReadRequest {
  591. GC_CELL(ByteStreamTeeDefaultReadRequest, ReadRequest);
  592. GC_DECLARE_ALLOCATOR(ByteStreamTeeDefaultReadRequest);
  593. public:
  594. ByteStreamTeeDefaultReadRequest(
  595. JS::Realm& realm,
  596. GC::Ref<ReadableStream> stream,
  597. GC::Ref<ByteStreamTeeParams> params,
  598. GC::Ref<WebIDL::Promise> cancel_promise)
  599. : m_realm(realm)
  600. , m_stream(stream)
  601. , m_params(params)
  602. , m_cancel_promise(cancel_promise)
  603. {
  604. }
  605. // https://streams.spec.whatwg.org/#ref-for-read-request-chunk-steps④
  606. virtual void on_chunk(JS::Value chunk) override
  607. {
  608. // 1. Queue a microtask to perform the following steps:
  609. HTML::queue_a_microtask(nullptr, GC::create_function(m_realm->heap(), [this, chunk]() mutable {
  610. HTML::TemporaryExecutionContext execution_context { m_realm, HTML::TemporaryExecutionContext::CallbacksEnabled::Yes };
  611. auto controller1 = m_params->branch1->controller()->get<GC::Ref<ReadableByteStreamController>>();
  612. auto controller2 = m_params->branch2->controller()->get<GC::Ref<ReadableByteStreamController>>();
  613. // 1. Set readAgainForBranch1 to false.
  614. m_params->read_again_for_branch1 = false;
  615. // 2. Set readAgainForBranch2 to false.
  616. m_params->read_again_for_branch2 = false;
  617. // 3. Let chunk1 and chunk2 be chunk.
  618. auto chunk1 = chunk;
  619. auto chunk2 = chunk;
  620. // 4. If canceled1 is false and canceled2 is false,
  621. if (!m_params->canceled1 && !m_params->canceled2) {
  622. // 1. Let cloneResult be CloneAsUint8Array(chunk).
  623. auto chunk_view = m_realm->create<WebIDL::ArrayBufferView>(chunk.as_object());
  624. auto clone_result = clone_as_uint8_array(m_realm, chunk_view);
  625. // 2. If cloneResult is an abrupt completion,
  626. if (clone_result.is_exception()) {
  627. auto completion = Bindings::exception_to_throw_completion(m_realm->vm(), clone_result.release_error());
  628. // 1. Perform ! ReadableByteStreamControllerError(branch1.[[controller]], cloneResult.[[Value]]).
  629. readable_byte_stream_controller_error(controller1, completion.value().value());
  630. // 2. Perform ! ReadableByteStreamControllerError(branch2.[[controller]], cloneResult.[[Value]]).
  631. readable_byte_stream_controller_error(controller2, completion.value().value());
  632. // 3. Resolve cancelPromise with ! ReadableStreamCancel(stream, cloneResult.[[Value]]).
  633. auto cancel_result = readable_stream_cancel(m_stream, completion.value().value());
  634. WebIDL::resolve_promise(m_realm, m_cancel_promise, cancel_result->promise());
  635. // 4. Return.
  636. return;
  637. }
  638. // 3. Otherwise, set chunk2 to cloneResult.[[Value]].
  639. chunk2 = clone_result.release_value();
  640. }
  641. // 5. If canceled1 is false, perform ! ReadableByteStreamControllerEnqueue(branch1.[[controller]], chunk1).
  642. if (!m_params->canceled1) {
  643. MUST(readable_byte_stream_controller_enqueue(controller1, chunk1));
  644. }
  645. // 6. If canceled2 is false, perform ! ReadableByteStreamControllerEnqueue(branch2.[[controller]], chunk2).
  646. if (!m_params->canceled2) {
  647. MUST(readable_byte_stream_controller_enqueue(controller2, chunk2));
  648. }
  649. // 7. Set reading to false.
  650. m_params->reading = false;
  651. // 8. If readAgainForBranch1 is true, perform pull1Algorithm.
  652. if (m_params->read_again_for_branch1) {
  653. m_params->pull1_algorithm->function()();
  654. }
  655. // 9. Otherwise, if readAgainForBranch2 is true, perform pull2Algorithm.
  656. else if (m_params->read_again_for_branch2) {
  657. m_params->pull2_algorithm->function()();
  658. }
  659. }));
  660. // NOTE: The microtask delay here is necessary because it takes at least a microtask to detect errors, when we
  661. // use reader.[[closedPromise]] below. We want errors in stream to error both branches immediately, so we
  662. // cannot let successful synchronously-available reads happen ahead of asynchronously-available errors.
  663. }
  664. // https://streams.spec.whatwg.org/#ref-for-read-request-close-steps③
  665. virtual void on_close() override
  666. {
  667. auto controller1 = m_params->branch1->controller()->get<GC::Ref<ReadableByteStreamController>>();
  668. auto controller2 = m_params->branch2->controller()->get<GC::Ref<ReadableByteStreamController>>();
  669. // 1. Set reading to false.
  670. m_params->reading = false;
  671. // 2. If canceled1 is false, perform ! ReadableByteStreamControllerClose(branch1.[[controller]]).
  672. if (!m_params->canceled1) {
  673. MUST(readable_byte_stream_controller_close(controller1));
  674. }
  675. // 3. If canceled2 is false, perform ! ReadableByteStreamControllerClose(branch2.[[controller]]).
  676. if (!m_params->canceled2) {
  677. MUST(readable_byte_stream_controller_close(controller2));
  678. }
  679. // 4. If branch1.[[controller]].[[pendingPullIntos]] is not empty, perform ! ReadableByteStreamControllerRespond(branch1.[[controller]], 0).
  680. if (!controller1->pending_pull_intos().is_empty()) {
  681. MUST(readable_byte_stream_controller_respond(controller1, 0));
  682. }
  683. // 5. If branch2.[[controller]].[[pendingPullIntos]] is not empty, perform ! ReadableByteStreamControllerRespond(branch2.[[controller]], 0).
  684. if (!controller2->pending_pull_intos().is_empty()) {
  685. MUST(readable_byte_stream_controller_respond(controller2, 0));
  686. }
  687. // 6. If canceled1 is false or canceled2 is false, resolve cancelPromise with undefined.
  688. if (!m_params->canceled1 || !m_params->canceled2) {
  689. WebIDL::resolve_promise(m_realm, m_cancel_promise, JS::js_undefined());
  690. }
  691. }
  692. // https://streams.spec.whatwg.org/#ref-for-read-request-error-steps④
  693. virtual void on_error(JS::Value) override
  694. {
  695. // 1. Set reading to false.
  696. m_params->reading = false;
  697. }
  698. private:
  699. virtual void visit_edges(Visitor& visitor) override
  700. {
  701. Base::visit_edges(visitor);
  702. visitor.visit(m_realm);
  703. visitor.visit(m_stream);
  704. visitor.visit(m_params);
  705. visitor.visit(m_cancel_promise);
  706. }
  707. GC::Ref<JS::Realm> m_realm;
  708. GC::Ref<ReadableStream> m_stream;
  709. GC::Ref<ByteStreamTeeParams> m_params;
  710. GC::Ref<WebIDL::Promise> m_cancel_promise;
  711. };
  712. GC_DEFINE_ALLOCATOR(ByteStreamTeeDefaultReadRequest);
  713. // https://streams.spec.whatwg.org/#ref-for-read-into-request②
  714. class ByteStreamTeeBYOBReadRequest final : public ReadIntoRequest {
  715. GC_CELL(ByteStreamTeeBYOBReadRequest, ReadIntoRequest);
  716. GC_DECLARE_ALLOCATOR(ByteStreamTeeBYOBReadRequest);
  717. public:
  718. ByteStreamTeeBYOBReadRequest(
  719. JS::Realm& realm,
  720. GC::Ref<ReadableStream> stream,
  721. GC::Ref<ByteStreamTeeParams> params,
  722. GC::Ref<WebIDL::Promise> cancel_promise,
  723. GC::Ref<ReadableStream> byob_branch,
  724. GC::Ref<ReadableStream> other_branch,
  725. bool for_branch2)
  726. : m_realm(realm)
  727. , m_stream(stream)
  728. , m_params(params)
  729. , m_cancel_promise(cancel_promise)
  730. , m_byob_branch(byob_branch)
  731. , m_other_branch(other_branch)
  732. , m_for_branch2(for_branch2)
  733. {
  734. }
  735. // https://streams.spec.whatwg.org/#ref-for-read-into-request-chunk-steps①
  736. virtual void on_chunk(JS::Value chunk) override
  737. {
  738. auto chunk_view = m_realm->create<WebIDL::ArrayBufferView>(chunk.as_object());
  739. // 1. Queue a microtask to perform the following steps:
  740. HTML::queue_a_microtask(nullptr, GC::create_function(m_realm->heap(), [this, chunk = chunk_view]() {
  741. HTML::TemporaryExecutionContext execution_context { m_realm, HTML::TemporaryExecutionContext::CallbacksEnabled::Yes };
  742. auto byob_controller = m_byob_branch->controller()->get<GC::Ref<ReadableByteStreamController>>();
  743. auto other_controller = m_other_branch->controller()->get<GC::Ref<ReadableByteStreamController>>();
  744. // 1. Set readAgainForBranch1 to false.
  745. m_params->read_again_for_branch1 = false;
  746. // 2. Set readAgainForBranch2 to false.
  747. m_params->read_again_for_branch2 = false;
  748. // 3. Let byobCanceled be canceled2 if forBranch2 is true, and canceled1 otherwise.
  749. auto byob_cancelled = m_for_branch2 ? m_params->canceled2 : m_params->canceled1;
  750. // 4. Let otherCanceled be canceled2 if forBranch2 is false, and canceled1 otherwise.
  751. auto other_cancelled = !m_for_branch2 ? m_params->canceled2 : m_params->canceled1;
  752. // 5. If otherCanceled is false,
  753. if (!other_cancelled) {
  754. // 1. Let cloneResult be CloneAsUint8Array(chunk).
  755. auto clone_result = clone_as_uint8_array(m_realm, chunk);
  756. // 2. If cloneResult is an abrupt completion,
  757. if (clone_result.is_exception()) {
  758. auto completion = Bindings::exception_to_throw_completion(m_realm->vm(), clone_result.release_error());
  759. // 1. Perform ! ReadableByteStreamControllerError(byobBranch.[[controller]], cloneResult.[[Value]]).
  760. readable_byte_stream_controller_error(byob_controller, completion.value().value());
  761. // 2. Perform ! ReadableByteStreamControllerError(otherBranch.[[controller]], cloneResult.[[Value]]).
  762. readable_byte_stream_controller_error(other_controller, completion.value().value());
  763. // 3. Resolve cancelPromise with ! ReadableStreamCancel(stream, cloneResult.[[Value]]).
  764. auto cancel_result = readable_stream_cancel(m_stream, completion.value().value());
  765. WebIDL::resolve_promise(m_realm, m_cancel_promise, cancel_result->promise());
  766. // 4. Return.
  767. return;
  768. }
  769. // 3. Otherwise, let clonedChunk be cloneResult.[[Value]].
  770. auto cloned_chunk = clone_result.release_value();
  771. // 4. If byobCanceled is false, perform ! ReadableByteStreamControllerRespondWithNewView(byobBranch.[[controller]], chunk).
  772. if (!byob_cancelled) {
  773. MUST(readable_byte_stream_controller_respond_with_new_view(m_realm, byob_controller, chunk));
  774. }
  775. // 5. Perform ! ReadableByteStreamControllerEnqueue(otherBranch.[[controller]], clonedChunk).
  776. MUST(readable_byte_stream_controller_enqueue(other_controller, cloned_chunk));
  777. }
  778. // 6. Otherwise, if byobCanceled is false, perform ! ReadableByteStreamControllerRespondWithNewView(byobBranch.[[controller]], chunk).
  779. else if (!byob_cancelled) {
  780. MUST(readable_byte_stream_controller_respond_with_new_view(m_realm, byob_controller, chunk));
  781. }
  782. // 7. Set reading to false.
  783. m_params->reading = false;
  784. // 8. If readAgainForBranch1 is true, perform pull1Algorithm.
  785. if (m_params->read_again_for_branch1) {
  786. m_params->pull1_algorithm->function()();
  787. }
  788. // 9. Otherwise, if readAgainForBranch2 is true, perform pull2Algorithm.
  789. else if (m_params->read_again_for_branch2) {
  790. m_params->pull2_algorithm->function()();
  791. }
  792. }));
  793. // NOTE: The microtask delay here is necessary because it takes at least a microtask to detect errors, when we
  794. // use reader.[[closedPromise]] below. We want errors in stream to error both branches immediately, so we
  795. // cannot let successful synchronously-available reads happen ahead of asynchronously-available errors.
  796. }
  797. // https://streams.spec.whatwg.org/#ref-for-read-into-request-close-steps②
  798. virtual void on_close(JS::Value chunk) override
  799. {
  800. auto byob_controller = m_byob_branch->controller()->get<GC::Ref<ReadableByteStreamController>>();
  801. auto other_controller = m_other_branch->controller()->get<GC::Ref<ReadableByteStreamController>>();
  802. // 1. Set reading to false.
  803. m_params->reading = false;
  804. // 2. Let byobCanceled be canceled2 if forBranch2 is true, and canceled1 otherwise.
  805. auto byob_cancelled = m_for_branch2 ? m_params->canceled2 : m_params->canceled1;
  806. // 3. Let otherCanceled be canceled2 if forBranch2 is false, and canceled1 otherwise.
  807. auto other_cancelled = !m_for_branch2 ? m_params->canceled2 : m_params->canceled1;
  808. // 4. If byobCanceled is false, perform ! ReadableByteStreamControllerClose(byobBranch.[[controller]]).
  809. if (!byob_cancelled) {
  810. MUST(readable_byte_stream_controller_close(byob_controller));
  811. }
  812. // 5. If otherCanceled is false, perform ! ReadableByteStreamControllerClose(otherBranch.[[controller]]).
  813. if (!other_cancelled) {
  814. MUST(readable_byte_stream_controller_close(other_controller));
  815. }
  816. // 6. If chunk is not undefined,
  817. if (!chunk.is_undefined()) {
  818. // 1. Assert: chunk.[[ByteLength]] is 0.
  819. // 2. If byobCanceled is false, perform ! ReadableByteStreamControllerRespondWithNewView(byobBranch.[[controller]], chunk).
  820. if (!byob_cancelled) {
  821. auto array_buffer_view = m_realm->create<WebIDL::ArrayBufferView>(chunk.as_object());
  822. MUST(readable_byte_stream_controller_respond_with_new_view(m_realm, byob_controller, array_buffer_view));
  823. }
  824. // 3. If otherCanceled is false and otherBranch.[[controller]].[[pendingPullIntos]] is not empty,
  825. // perform ! ReadableByteStreamControllerRespond(otherBranch.[[controller]], 0).
  826. if (!other_cancelled && !other_controller->pending_pull_intos().is_empty()) {
  827. MUST(readable_byte_stream_controller_respond(other_controller, 0));
  828. }
  829. }
  830. // 7. If byobCanceled is false or otherCanceled is false, resolve cancelPromise with undefined.
  831. if (!byob_cancelled || !other_cancelled) {
  832. WebIDL::resolve_promise(m_realm, m_cancel_promise, JS::js_undefined());
  833. }
  834. }
  835. // https://streams.spec.whatwg.org/#ref-for-read-into-request-error-steps①
  836. virtual void on_error(JS::Value) override
  837. {
  838. // 1. Set reading to false.
  839. m_params->reading = false;
  840. }
  841. private:
  842. virtual void visit_edges(Visitor& visitor) override
  843. {
  844. Base::visit_edges(visitor);
  845. visitor.visit(m_realm);
  846. visitor.visit(m_stream);
  847. visitor.visit(m_params);
  848. visitor.visit(m_cancel_promise);
  849. visitor.visit(m_byob_branch);
  850. visitor.visit(m_other_branch);
  851. }
  852. GC::Ref<JS::Realm> m_realm;
  853. GC::Ref<ReadableStream> m_stream;
  854. GC::Ref<ByteStreamTeeParams> m_params;
  855. GC::Ref<WebIDL::Promise> m_cancel_promise;
  856. GC::Ref<ReadableStream> m_byob_branch;
  857. GC::Ref<ReadableStream> m_other_branch;
  858. bool m_for_branch2 { false };
  859. };
  860. GC_DEFINE_ALLOCATOR(ByteStreamTeeBYOBReadRequest);
  861. // https://streams.spec.whatwg.org/#abstract-opdef-readablebytestreamtee
  862. WebIDL::ExceptionOr<ReadableStreamPair> readable_byte_stream_tee(JS::Realm& realm, ReadableStream& stream)
  863. {
  864. // 1. Assert: stream implements ReadableStream.
  865. // 2. Assert: stream.[[controller]] implements ReadableByteStreamController.
  866. VERIFY(stream.controller().has_value() && stream.controller()->has<GC::Ref<ReadableByteStreamController>>());
  867. // 3. Let reader be ? AcquireReadableStreamDefaultReader(stream).
  868. auto reader = TRY(acquire_readable_stream_default_reader(stream));
  869. // 4. Let reading be false.
  870. // 5. Let readAgainForBranch1 be false.
  871. // 6. Let readAgainForBranch2 be false.
  872. // 7. Let canceled1 be false.
  873. // 8. Let canceled2 be false.
  874. // 9. Let reason1 be undefined.
  875. // 10. Let reason2 be undefined.
  876. // 11. Let branch1 be undefined.
  877. // 12. Let branch2 be undefined.
  878. auto params = realm.create<ByteStreamTeeParams>(reader);
  879. // 13. Let cancelPromise be a new promise.
  880. auto cancel_promise = WebIDL::create_promise(realm);
  881. // 14. Let forwardReaderError be the following steps, taking a thisReader argument:
  882. auto forward_reader_error = GC::create_function(realm.heap(), [&realm, params, cancel_promise](ReadableStreamReader const& this_reader) {
  883. // 1. Upon rejection of thisReader.[[closedPromise]] with reason r,
  884. auto closed_promise = this_reader.visit([](auto const& underlying_reader) { return underlying_reader->closed_promise_capability(); });
  885. WebIDL::upon_rejection(*closed_promise, GC::create_function(realm.heap(), [&realm, this_reader, params, cancel_promise](JS::Value reason) -> WebIDL::ExceptionOr<JS::Value> {
  886. auto controller1 = params->branch1->controller()->get<GC::Ref<ReadableByteStreamController>>();
  887. auto controller2 = params->branch2->controller()->get<GC::Ref<ReadableByteStreamController>>();
  888. // 1. If thisReader is not reader, return.
  889. if (this_reader != params->reader) {
  890. return JS::js_undefined();
  891. }
  892. // 2. Perform ! ReadableByteStreamControllerError(branch1.[[controller]], r).
  893. readable_byte_stream_controller_error(controller1, reason);
  894. // 3. Perform ! ReadableByteStreamControllerError(branch2.[[controller]], r).
  895. readable_byte_stream_controller_error(controller2, reason);
  896. // 4. If canceled1 is false or canceled2 is false, resolve cancelPromise with undefined.
  897. if (!params->canceled1 || !params->canceled2) {
  898. WebIDL::resolve_promise(realm, cancel_promise, JS::js_undefined());
  899. }
  900. return JS::js_undefined();
  901. }));
  902. });
  903. // 15. Let pullWithDefaultReader be the following steps:
  904. auto pull_with_default_reader = GC::create_function(realm.heap(), [&realm, &stream, params, cancel_promise, forward_reader_error]() mutable {
  905. // 1. If reader implements ReadableStreamBYOBReader,
  906. if (auto const* byob_reader = params->reader.get_pointer<GC::Ref<ReadableStreamBYOBReader>>()) {
  907. // 1. Assert: reader.[[readIntoRequests]] is empty.
  908. VERIFY((*byob_reader)->read_into_requests().is_empty());
  909. // 2. Perform ! ReadableStreamBYOBReaderRelease(reader).
  910. readable_stream_byob_reader_release(*byob_reader);
  911. // 3. Set reader to ! AcquireReadableStreamDefaultReader(stream).
  912. params->reader = MUST(acquire_readable_stream_default_reader(stream));
  913. // 4. Perform forwardReaderError, given reader.
  914. forward_reader_error->function()(params->reader);
  915. }
  916. // 2. Let readRequest be a read request with the following items:
  917. auto read_request = realm.heap().allocate<ByteStreamTeeDefaultReadRequest>(realm, stream, params, cancel_promise);
  918. // 3. Perform ! ReadableStreamDefaultReaderRead(reader, readRequest).
  919. readable_stream_default_reader_read(params->reader.get<GC::Ref<ReadableStreamDefaultReader>>(), read_request);
  920. });
  921. // 16. Let pullWithBYOBReader be the following steps, given view and forBranch2:
  922. auto pull_with_byob_reader = GC::create_function(realm.heap(), [&realm, &stream, params, cancel_promise, forward_reader_error](GC::Ref<WebIDL::ArrayBufferView> view, bool for_branch2) mutable {
  923. // 1. If reader implements ReadableStreamDefaultReader,
  924. if (auto const* default_reader = params->reader.get_pointer<GC::Ref<ReadableStreamDefaultReader>>()) {
  925. // 2. Assert: reader.[[readRequests]] is empty.
  926. VERIFY((*default_reader)->read_requests().is_empty());
  927. // 3. Perform ! ReadableStreamDefaultReaderRelease(reader).
  928. readable_stream_default_reader_release(*default_reader);
  929. // 4. Set reader to ! AcquireReadableStreamBYOBReader(stream).
  930. params->reader = MUST(acquire_readable_stream_byob_reader(stream));
  931. // 5. Perform forwardReaderError, given reader.
  932. forward_reader_error->function()(params->reader);
  933. };
  934. // 2. Let byobBranch be branch2 if forBranch2 is true, and branch1 otherwise.
  935. auto byob_branch = for_branch2 ? params->branch2 : params->branch1;
  936. // 3. Let otherBranch be branch2 if forBranch2 is false, and branch1 otherwise.
  937. auto other_branch = !for_branch2 ? params->branch2 : params->branch1;
  938. // 4. Let readIntoRequest be a read-into request with the following items:
  939. auto read_into_request = realm.heap().allocate<ByteStreamTeeBYOBReadRequest>(realm, stream, params, cancel_promise, *byob_branch, *other_branch, for_branch2);
  940. // 5. Perform ! ReadableStreamBYOBReaderRead(reader, view, 1, readIntoRequest).
  941. readable_stream_byob_reader_read(params->reader.get<GC::Ref<ReadableStreamBYOBReader>>(), view, 1, read_into_request);
  942. });
  943. // 17. Let pull1Algorithm be the following steps:
  944. auto pull1_algorithm = GC::create_function(realm.heap(), [&realm, params, pull_with_default_reader, pull_with_byob_reader]() {
  945. auto controller1 = params->branch1->controller()->get<GC::Ref<ReadableByteStreamController>>();
  946. // 1. If reading is true,
  947. if (params->reading) {
  948. // 1. Set readAgainForBranch1 to true.
  949. params->read_again_for_branch1 = true;
  950. // 2. Return a promise resolved with undefined.
  951. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  952. }
  953. // 2. Set reading to true.
  954. params->reading = true;
  955. // 3. Let byobRequest be ! ReadableByteStreamControllerGetBYOBRequest(branch1.[[controller]]).
  956. auto byob_request = readable_byte_stream_controller_get_byob_request(controller1);
  957. // 4. If byobRequest is null, perform pullWithDefaultReader.
  958. if (!byob_request) {
  959. pull_with_default_reader->function()();
  960. }
  961. // 5. Otherwise, perform pullWithBYOBReader, given byobRequest.[[view]] and false.
  962. else {
  963. pull_with_byob_reader->function()(*byob_request->view(), false);
  964. }
  965. // 6. Return a promise resolved with undefined.
  966. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  967. });
  968. // 18. Let pull2Algorithm be the following steps:
  969. auto pull2_algorithm = GC::create_function(realm.heap(), [&realm, params, pull_with_default_reader, pull_with_byob_reader]() {
  970. auto controller2 = params->branch2->controller()->get<GC::Ref<ReadableByteStreamController>>();
  971. // 1. If reading is true,
  972. if (params->reading) {
  973. // 1. Set readAgainForBranch2 to true.
  974. params->read_again_for_branch2 = true;
  975. // 2. Return a promise resolved with undefined.
  976. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  977. }
  978. // 2. Set reading to true.
  979. params->reading = true;
  980. // 3. Let byobRequest be ! ReadableByteStreamControllerGetBYOBRequest(branch2.[[controller]]).
  981. auto byob_request = readable_byte_stream_controller_get_byob_request(controller2);
  982. // 4. If byobRequest is null, perform pullWithDefaultReader.
  983. if (!byob_request) {
  984. pull_with_default_reader->function()();
  985. }
  986. // 5. Otherwise, perform pullWithBYOBReader, given byobRequest.[[view]] and true.
  987. else {
  988. pull_with_byob_reader->function()(*byob_request->view(), true);
  989. }
  990. // 6. Return a promise resolved with undefined.
  991. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  992. });
  993. // AD-HOC: The read requests within the pull algorithms must be able to re-invoke the pull algorithms, so cache them here.
  994. params->pull1_algorithm = pull1_algorithm;
  995. params->pull2_algorithm = pull2_algorithm;
  996. // 19. Let cancel1Algorithm be the following steps, taking a reason argument:
  997. auto cancel1_algorithm = GC::create_function(realm.heap(), [&realm, &stream, params, cancel_promise](JS::Value reason) {
  998. // 1. Set canceled1 to true.
  999. params->canceled1 = true;
  1000. // 2. Set reason1 to reason.
  1001. params->reason1 = reason;
  1002. // 3. If canceled2 is true,
  1003. if (params->canceled2) {
  1004. // 1. Let compositeReason be ! CreateArrayFromList(« reason1, reason2 »).
  1005. auto composite_reason = JS::Array::create_from(realm, AK::Array { params->reason1, params->reason2 });
  1006. // 2. Let cancelResult be ! ReadableStreamCancel(stream, compositeReason).
  1007. auto cancel_result = readable_stream_cancel(stream, composite_reason);
  1008. // 3. Resolve cancelPromise with cancelResult.
  1009. WebIDL::resolve_promise(realm, cancel_promise, cancel_result->promise());
  1010. }
  1011. // 4. Return cancelPromise.
  1012. return cancel_promise;
  1013. });
  1014. // 20. Let cancel2Algorithm be the following steps, taking a reason argument:
  1015. auto cancel2_algorithm = GC::create_function(realm.heap(), [&realm, &stream, params, cancel_promise](JS::Value reason) {
  1016. // 1. Set canceled2 to true.
  1017. params->canceled2 = true;
  1018. // 2. Set reason2 to reason.
  1019. params->reason2 = reason;
  1020. // 3. If canceled1 is true,
  1021. if (params->canceled1) {
  1022. // 1. Let compositeReason be ! CreateArrayFromList(« reason1, reason2 »).
  1023. auto composite_reason = JS::Array::create_from(realm, AK::Array { params->reason1, params->reason2 });
  1024. // 2. Let cancelResult be ! ReadableStreamCancel(stream, compositeReason).
  1025. auto cancel_result = readable_stream_cancel(stream, composite_reason);
  1026. // 3. Resolve cancelPromise with cancelResult.
  1027. WebIDL::resolve_promise(realm, cancel_promise, cancel_result->promise());
  1028. }
  1029. // 4. Return cancelPromise.
  1030. return cancel_promise;
  1031. });
  1032. // 21. Let startAlgorithm be an algorithm that returns undefined.
  1033. auto start_algorithm = GC::create_function(realm.heap(), []() -> WebIDL::ExceptionOr<JS::Value> {
  1034. return JS::js_undefined();
  1035. });
  1036. // 22. Set branch1 to ! CreateReadableByteStream(startAlgorithm, pull1Algorithm, cancel1Algorithm).
  1037. params->branch1 = MUST(create_readable_byte_stream(realm, start_algorithm, pull1_algorithm, cancel1_algorithm));
  1038. // 23. Set branch2 to ! CreateReadableByteStream(startAlgorithm, pull2Algorithm, cancel2Algorithm).
  1039. params->branch2 = MUST(create_readable_byte_stream(realm, start_algorithm, pull2_algorithm, cancel2_algorithm));
  1040. // 24. Perform forwardReaderError, given reader.
  1041. forward_reader_error->function()(reader);
  1042. // 25. Return « branch1, branch2 ».
  1043. return ReadableStreamPair { *params->branch1, *params->branch2 };
  1044. }
  1045. // https://streams.spec.whatwg.org/#make-size-algorithm-from-size-function
  1046. GC::Ref<SizeAlgorithm> extract_size_algorithm(JS::VM& vm, QueuingStrategy const& strategy)
  1047. {
  1048. // 1. If strategy["size"] does not exist, return an algorithm that returns 1.
  1049. if (!strategy.size)
  1050. return GC::create_function(vm.heap(), [](JS::Value) { return JS::normal_completion(JS::Value(1)); });
  1051. // 2. Return an algorithm that performs the following steps, taking a chunk argument:
  1052. return GC::create_function(vm.heap(), [size = strategy.size](JS::Value chunk) {
  1053. return WebIDL::invoke_callback(*size, JS::js_undefined(), chunk);
  1054. });
  1055. }
  1056. // https://streams.spec.whatwg.org/#validate-and-normalize-high-water-mark
  1057. WebIDL::ExceptionOr<double> extract_high_water_mark(QueuingStrategy const& strategy, double default_hwm)
  1058. {
  1059. // 1. If strategy["highWaterMark"] does not exist, return defaultHWM.
  1060. if (!strategy.high_water_mark.has_value())
  1061. return default_hwm;
  1062. // 2. Let highWaterMark be strategy["highWaterMark"].
  1063. auto high_water_mark = strategy.high_water_mark.value();
  1064. // 3. If highWaterMark is NaN or highWaterMark < 0, throw a RangeError exception.
  1065. if (isnan(high_water_mark) || high_water_mark < 0)
  1066. return WebIDL::SimpleException { WebIDL::SimpleExceptionType::RangeError, "Invalid value for high water mark"sv };
  1067. // 4. Return highWaterMark.
  1068. return high_water_mark;
  1069. }
  1070. // https://streams.spec.whatwg.org/#readable-stream-close
  1071. void readable_stream_close(ReadableStream& stream)
  1072. {
  1073. auto& realm = stream.realm();
  1074. // 1. Assert: stream.[[state]] is "readable".
  1075. VERIFY(stream.state() == ReadableStream::State::Readable);
  1076. // 2. Set stream.[[state]] to "closed".
  1077. stream.set_state(ReadableStream::State::Closed);
  1078. // 3. Let reader be stream.[[reader]].
  1079. auto reader = stream.reader();
  1080. // 4. If reader is undefined, return.
  1081. if (!reader.has_value())
  1082. return;
  1083. // 5. Resolve reader.[[closedPromise]] with undefined.
  1084. WebIDL::resolve_promise(realm, *reader->visit([](auto& reader) {
  1085. return reader->closed_promise_capability();
  1086. }));
  1087. // 6. If reader implements ReadableStreamDefaultReader,
  1088. if (reader->has<GC::Ref<ReadableStreamDefaultReader>>()) {
  1089. // 1. Let readRequests be reader.[[readRequests]].
  1090. // 2. Set reader.[[readRequests]] to an empty list.
  1091. auto read_requests = move(reader->get<GC::Ref<ReadableStreamDefaultReader>>()->read_requests());
  1092. // 3. For each readRequest of readRequests,
  1093. for (auto& read_request : read_requests) {
  1094. // 1. Perform readRequest’s close steps.
  1095. read_request->on_close();
  1096. }
  1097. }
  1098. }
  1099. // https://streams.spec.whatwg.org/#readable-stream-error
  1100. void readable_stream_error(ReadableStream& stream, JS::Value error)
  1101. {
  1102. auto& realm = stream.realm();
  1103. // 1. Assert: stream.[[state]] is "readable".
  1104. VERIFY(stream.state() == ReadableStream::State::Readable);
  1105. // 2. Set stream.[[state]] to "errored".
  1106. stream.set_state(ReadableStream::State::Errored);
  1107. // 3. Set stream.[[storedError]] to e.
  1108. stream.set_stored_error(error);
  1109. // 4. Let reader be stream.[[reader]].
  1110. auto reader = stream.reader();
  1111. // 5. If reader is undefined, return.
  1112. if (!reader.has_value())
  1113. return;
  1114. auto closed_promise_capability = reader->visit([](auto& reader) { return reader->closed_promise_capability(); });
  1115. // 6. Reject reader.[[closedPromise]] with e.
  1116. WebIDL::reject_promise(realm, *closed_promise_capability, error);
  1117. // 7. Set reader.[[closedPromise]].[[PromiseIsHandled]] to true.
  1118. WebIDL::mark_promise_as_handled(*closed_promise_capability);
  1119. // 8. If reader implements ReadableStreamDefaultReader,
  1120. if (reader->has<GC::Ref<ReadableStreamDefaultReader>>()) {
  1121. // 1. Perform ! ReadableStreamDefaultReaderErrorReadRequests(reader, e).
  1122. readable_stream_default_reader_error_read_requests(*reader->get<GC::Ref<ReadableStreamDefaultReader>>(), error);
  1123. }
  1124. // 9. Otherwise,
  1125. else {
  1126. // 1. Assert: reader implements ReadableStreamBYOBReader.
  1127. VERIFY(reader->has<GC::Ref<ReadableStreamBYOBReader>>());
  1128. // 2. Perform ! ReadableStreamBYOBReaderErrorReadIntoRequests(reader, e).
  1129. readable_stream_byob_reader_error_read_into_requests(*reader->get<GC::Ref<ReadableStreamBYOBReader>>(), error);
  1130. }
  1131. }
  1132. // https://streams.spec.whatwg.org/#readable-stream-from-iterable
  1133. WebIDL::ExceptionOr<GC::Ref<ReadableStream>> readable_stream_from_iterable(JS::VM& vm, JS::Value async_iterable)
  1134. {
  1135. auto& realm = *vm.current_realm();
  1136. // 1. Let stream be undefined.
  1137. // NON-STANDARD: We capture 'stream' in a lambda later, so it needs to be allocated now.
  1138. // 'stream' is still in an uninitialized state and will be initialized / set up at step 6.
  1139. auto stream = realm.create<ReadableStream>(realm);
  1140. // 2. Let iteratorRecord be ? GetIterator(asyncIterable, async).
  1141. auto iterator_record = TRY(JS::get_iterator(vm, async_iterable, JS::IteratorHint::Async));
  1142. // 3. Let startAlgorithm be an algorithm that returns undefined.
  1143. auto start_algorithm = GC::create_function(realm.heap(), []() -> WebIDL::ExceptionOr<JS::Value> {
  1144. return JS::js_undefined();
  1145. });
  1146. // 4. Let pullAlgorithm be the following steps:
  1147. auto pull_algorithm = GC::create_function(realm.heap(), [&vm, &realm, stream, iterator_record]() mutable {
  1148. // 1. Let nextResult be IteratorNext(iteratorRecord).
  1149. auto next_result = JS::iterator_next(vm, iterator_record);
  1150. // 2. If nextResult is an abrupt completion, return a promise rejected with nextResult.[[Value]].
  1151. if (next_result.is_error())
  1152. return WebIDL::create_rejected_promise(realm, *next_result.throw_completion().release_value());
  1153. // 3. Let nextPromise be a promise resolved with nextResult.[[Value]].
  1154. auto next_promise = WebIDL::create_resolved_promise(realm, next_result.release_value());
  1155. // 4. Return the result of reacting to nextPromise with the following fulfillment steps, given iterResult:
  1156. auto react_result = WebIDL::react_to_promise(*next_promise,
  1157. GC::create_function(realm.heap(), [&vm, stream](JS::Value iter_result) -> WebIDL::ExceptionOr<JS::Value> {
  1158. // 1. If iterResult is not an Object, throw a TypeError.
  1159. if (!iter_result.is_object())
  1160. return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "iterResult is not an Object"sv };
  1161. // 2. Let done be ? IteratorComplete(iterResult).
  1162. auto done = TRY(JS::iterator_complete(vm, iter_result.as_object()));
  1163. // 3. If done is true:
  1164. if (done) {
  1165. // 1. Perform ! ReadableStreamDefaultControllerClose(stream.[[controller]]).
  1166. readable_stream_default_controller_close(*stream->controller()->get<GC::Ref<ReadableStreamDefaultController>>());
  1167. }
  1168. // 4. Otherwise:
  1169. else {
  1170. // 1. Let value be ? IteratorValue(iterResult).
  1171. auto value = TRY(JS::iterator_value(vm, iter_result.as_object()));
  1172. // 2. Perform ! ReadableStreamDefaultControllerEnqueue(stream.[[controller]], value).
  1173. MUST(readable_stream_default_controller_enqueue(*stream->controller()->get<GC::Ref<ReadableStreamDefaultController>>(), value));
  1174. }
  1175. return JS::js_undefined();
  1176. }),
  1177. {});
  1178. return react_result;
  1179. });
  1180. // 5. Let cancelAlgorithm be the following steps, given reason:
  1181. auto cancel_algorithm = GC::create_function(realm.heap(), [&vm, &realm, iterator_record](JS::Value reason) {
  1182. // 1. Let iterator be iteratorRecord.[[Iterator]].
  1183. auto iterator = iterator_record->iterator;
  1184. // 2. Let returnMethod be GetMethod(iterator, "return").
  1185. auto return_method = iterator->get(vm.names.return_);
  1186. // 3. If returnMethod is an abrupt completion, return a promise rejected with returnMethod.[[Value]].
  1187. if (return_method.is_error())
  1188. return WebIDL::create_rejected_promise(realm, *return_method.throw_completion().release_value());
  1189. // 4. If returnMethod.[[Value]] is undefined, return a promise resolved with undefined.
  1190. if (return_method.value().is_undefined())
  1191. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  1192. // 5. Let returnResult be Call(returnMethod.[[Value]], iterator, « reason »).
  1193. auto return_result = JS::call(vm, return_method.value(), reason);
  1194. // 6. If returnResult is an abrupt completion, return a promise rejected with returnResult.[[Value]].
  1195. if (return_result.is_error())
  1196. return WebIDL::create_rejected_promise(realm, *return_result.throw_completion().release_value());
  1197. // 7. Let returnPromise be a promise resolved with returnResult.[[Value]].
  1198. auto return_promise = WebIDL::create_resolved_promise(realm, return_result.release_value());
  1199. // 8. Return the result of reacting to returnPromise with the following fulfillment steps, given iterResult:
  1200. auto react_result = WebIDL::react_to_promise(*return_promise,
  1201. GC::create_function(realm.heap(), [](JS::Value iter_result) -> WebIDL::ExceptionOr<JS::Value> {
  1202. // 1. If iterResult is not an Object, throw a TypeError.
  1203. if (!iter_result.is_object())
  1204. return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "iterResult is not an Object"sv };
  1205. // 2. Return undefined.
  1206. return JS::js_undefined();
  1207. }),
  1208. {});
  1209. return react_result;
  1210. });
  1211. // 6. Set stream to ! CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, 0).
  1212. // NON-STANDARD: 'stream' is captured in a lambda defined earlier, so we cannot overwrite it by assigning the ReadableStream returned by CreateReadableStream.
  1213. MUST(set_up_readable_stream(realm, *stream, start_algorithm, pull_algorithm, cancel_algorithm, 0));
  1214. // 7. Return stream.
  1215. return stream;
  1216. }
  1217. // https://streams.spec.whatwg.org/#readable-stream-add-read-request
  1218. void readable_stream_add_read_request(ReadableStream& stream, GC::Ref<ReadRequest> read_request)
  1219. {
  1220. // 1. Assert: stream.[[reader]] implements ReadableStreamDefaultReader.
  1221. VERIFY(stream.reader().has_value() && stream.reader()->has<GC::Ref<ReadableStreamDefaultReader>>());
  1222. // 2. Assert: stream.[[state]] is "readable".
  1223. VERIFY(stream.state() == ReadableStream::State::Readable);
  1224. // 3. Append readRequest to stream.[[reader]].[[readRequests]].
  1225. stream.reader()->get<GC::Ref<ReadableStreamDefaultReader>>()->read_requests().append(read_request);
  1226. }
  1227. // https://streams.spec.whatwg.org/#readable-stream-add-read-into-request
  1228. void readable_stream_add_read_into_request(ReadableStream& stream, GC::Ref<ReadIntoRequest> read_into_request)
  1229. {
  1230. // 1. Assert: stream.[[reader]] implements ReadableStreamBYOBReader.
  1231. VERIFY(stream.reader().has_value() && stream.reader()->has<GC::Ref<ReadableStreamBYOBReader>>());
  1232. // 2. Assert: stream.[[state]] is "readable" or "closed".
  1233. VERIFY(stream.is_readable() || stream.is_closed());
  1234. // 3. Append readRequest to stream.[[reader]].[[readIntoRequests]].
  1235. stream.reader()->get<GC::Ref<ReadableStreamBYOBReader>>()->read_into_requests().append(read_into_request);
  1236. }
  1237. // https://streams.spec.whatwg.org/#readable-stream-reader-generic-cancel
  1238. GC::Ref<WebIDL::Promise> readable_stream_reader_generic_cancel(ReadableStreamGenericReaderMixin& reader, JS::Value reason)
  1239. {
  1240. // 1. Let stream be reader.[[stream]]
  1241. auto stream = reader.stream();
  1242. // 2. Assert: stream is not undefined
  1243. VERIFY(stream);
  1244. // 3. Return ! ReadableStreamCancel(stream, reason)
  1245. return readable_stream_cancel(*stream, reason);
  1246. }
  1247. // https://streams.spec.whatwg.org/#readable-stream-reader-generic-initialize
  1248. void readable_stream_reader_generic_initialize(ReadableStreamReader reader, ReadableStream& stream)
  1249. {
  1250. auto& realm = stream.realm();
  1251. // 1. Set reader.[[stream]] to stream.
  1252. reader.visit([&](auto& reader) { reader->set_stream(stream); });
  1253. // 2. Set stream.[[reader]] to reader.
  1254. stream.set_reader(reader);
  1255. // 3. If stream.[[state]] is "readable",
  1256. if (stream.state() == ReadableStream::State::Readable) {
  1257. // 1. Set reader.[[closedPromise]] to a new promise.
  1258. reader.visit([&](auto& reader) { reader->set_closed_promise_capability(WebIDL::create_promise(realm)); });
  1259. }
  1260. // 4. Otherwise, if stream.[[state]] is "closed",
  1261. else if (stream.state() == ReadableStream::State::Closed) {
  1262. // 1. Set reader.[[closedPromise]] to a promise resolved with undefined.
  1263. reader.visit([&](auto& reader) {
  1264. reader->set_closed_promise_capability(WebIDL::create_resolved_promise(realm, JS::js_undefined()));
  1265. });
  1266. }
  1267. // 5. Otherwise,
  1268. else {
  1269. // 1. Assert: stream.[[state]] is "errored".
  1270. VERIFY(stream.state() == ReadableStream::State::Errored);
  1271. // 2. Set reader.[[closedPromise]] to a promise rejected with stream.[[storedError]].
  1272. // 3. Set reader.[[closedPromise]].[[PromiseIsHandled]] to true.
  1273. reader.visit([&](auto& reader) {
  1274. reader->set_closed_promise_capability(WebIDL::create_rejected_promise(realm, stream.stored_error()));
  1275. WebIDL::mark_promise_as_handled(*reader->closed_promise_capability());
  1276. });
  1277. }
  1278. }
  1279. // https://streams.spec.whatwg.org/#readable-stream-reader-generic-release
  1280. void readable_stream_reader_generic_release(ReadableStreamGenericReaderMixin& reader)
  1281. {
  1282. // 1. Let stream be reader.[[stream]].
  1283. auto stream = reader.stream();
  1284. // 2. Assert: stream is not undefined.
  1285. VERIFY(stream);
  1286. // 3. Assert: stream.[[reader]] is reader.
  1287. VERIFY(stream->reader()->visit([](auto& reader) -> ReadableStreamGenericReaderMixin* { return reader.ptr(); }) == &reader);
  1288. auto& realm = stream->realm();
  1289. // 4. If stream.[[state]] is "readable", reject reader.[[closedPromise]] with a TypeError exception.
  1290. auto exception = JS::TypeError::create(realm, "Released readable stream"sv);
  1291. if (stream->is_readable()) {
  1292. WebIDL::reject_promise(realm, *reader.closed_promise_capability(), exception);
  1293. }
  1294. // 5. Otherwise, set reader.[[closedPromise]] to a promise rejected with a TypeError exception.
  1295. else {
  1296. reader.set_closed_promise_capability(WebIDL::create_rejected_promise(realm, exception));
  1297. }
  1298. // 6. Set reader.[[closedPromise]].[[PromiseIsHandled]] to true.
  1299. WebIDL::mark_promise_as_handled(*reader.closed_promise_capability());
  1300. // 7. Perform ! stream.[[controller]].[[ReleaseSteps]]().
  1301. stream->controller()->visit([](auto const& controller) { return controller->release_steps(); });
  1302. // 8. Set stream.[[reader]] to undefined.
  1303. stream->set_reader({});
  1304. // 9. Set reader.[[stream]] to undefined.
  1305. reader.set_stream({});
  1306. }
  1307. // https://streams.spec.whatwg.org/#abstract-opdef-readablestreamdefaultreadererrorreadrequests
  1308. void readable_stream_default_reader_error_read_requests(ReadableStreamDefaultReader& reader, JS::Value error)
  1309. {
  1310. // 1. Let readRequests be reader.[[readRequests]].
  1311. auto read_requests = move(reader.read_requests());
  1312. // 2. Set reader.[[readRequests]] to a new empty list.
  1313. reader.read_requests().clear();
  1314. // 3. For each readRequest of readRequests,
  1315. for (auto& read_request : read_requests) {
  1316. // 1. Perform readRequest’s error steps, given e.
  1317. read_request->on_error(error);
  1318. }
  1319. }
  1320. // https://streams.spec.whatwg.org/#abstract-opdef-readablestreambyobreadererrorreadintorequests
  1321. void readable_stream_byob_reader_error_read_into_requests(ReadableStreamBYOBReader& reader, JS::Value error)
  1322. {
  1323. // 1. Let readIntoRequests be reader.[[readIntoRequests]].
  1324. auto read_into_requests = move(reader.read_into_requests());
  1325. // 2. Set reader.[[readIntoRequests]] to a new empty list.
  1326. reader.read_into_requests().clear();
  1327. // 3. For each readIntoRequest of readIntoRequests,
  1328. for (auto& read_into_request : read_into_requests) {
  1329. // 1. Perform readIntoRequest’s error steps, given e.
  1330. read_into_request->on_error(error);
  1331. }
  1332. }
  1333. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-fill-head-pull-into-descriptor
  1334. void readable_byte_stream_controller_fill_head_pull_into_descriptor(ReadableByteStreamController const& controller, u64 size, PullIntoDescriptor& pull_into_descriptor)
  1335. {
  1336. // 1. Assert: either controller.[[pendingPullIntos]] is empty, or controller.[[pendingPullIntos]][0] is pullIntoDescriptor.
  1337. VERIFY(controller.pending_pull_intos().is_empty() || &controller.pending_pull_intos().first() == &pull_into_descriptor);
  1338. // 2. Assert: controller.[[byobRequest]] is null.
  1339. VERIFY(!controller.raw_byob_request());
  1340. // 3. Set pullIntoDescriptor’s bytes filled to bytes filled + size.
  1341. pull_into_descriptor.bytes_filled += size;
  1342. }
  1343. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-fill-pull-into-descriptor-from-queue
  1344. bool readable_byte_stream_controller_fill_pull_into_descriptor_from_queue(ReadableByteStreamController& controller, PullIntoDescriptor& pull_into_descriptor)
  1345. {
  1346. // 1. Let maxBytesToCopy be min(controller.[[queueTotalSize]], pullIntoDescriptor’s byte length − pullIntoDescriptor’s bytes filled).
  1347. auto max_bytes_to_copy = min(controller.queue_total_size(), pull_into_descriptor.byte_length - pull_into_descriptor.bytes_filled);
  1348. // 2. Let maxBytesFilled be pullIntoDescriptor’s bytes filled + maxBytesToCopy.
  1349. u64 max_bytes_filled = pull_into_descriptor.bytes_filled + max_bytes_to_copy;
  1350. // 3. Let totalBytesToCopyRemaining be maxBytesToCopy.
  1351. auto total_bytes_to_copy_remaining = max_bytes_to_copy;
  1352. // 4. Let ready be false.
  1353. bool ready = false;
  1354. // 5. Assert: ! IsDetachedBuffer(pullIntoDescriptor’s buffer) is false.
  1355. VERIFY(!pull_into_descriptor.buffer->is_detached());
  1356. // 6. Assert: pullIntoDescriptor’s bytes filled < pullIntoDescriptor’s minimum fill.
  1357. VERIFY(pull_into_descriptor.bytes_filled < pull_into_descriptor.minimum_fill);
  1358. // 7. Let remainderBytes be the remainder after dividing maxBytesFilled by pullIntoDescriptor’s element size.
  1359. auto remainder_bytes = max_bytes_filled % pull_into_descriptor.element_size;
  1360. // 8. Let maxAlignedBytes be maxBytesFilled − remainderBytes.
  1361. auto max_aligned_bytes = max_bytes_filled - remainder_bytes;
  1362. // 9. If maxAlignedBytes ≥ pullIntoDescriptor’s minimum fill,
  1363. if (max_aligned_bytes >= pull_into_descriptor.minimum_fill) {
  1364. // 1. Set totalBytesToCopyRemaining to maxAlignedBytes − pullIntoDescriptor’s bytes filled.
  1365. total_bytes_to_copy_remaining = max_aligned_bytes - pull_into_descriptor.bytes_filled;
  1366. // 2. Set ready to true.
  1367. ready = true;
  1368. // NOTE: A descriptor for a read() request that is not yet filled up to its minimum length will stay at the head of the queue, so the underlying source can keep filling it.
  1369. }
  1370. // 10. Let queue be controller.[[queue]].
  1371. auto& queue = controller.queue();
  1372. // 11. While totalBytesToCopyRemaining > 0,
  1373. while (total_bytes_to_copy_remaining > 0) {
  1374. // 1. Let headOfQueue be queue[0].
  1375. auto& head_of_queue = queue.first();
  1376. // 2. Let bytesToCopy be min(totalBytesToCopyRemaining, headOfQueue’s byte length).
  1377. auto bytes_to_copy = min(total_bytes_to_copy_remaining, head_of_queue.byte_length);
  1378. // 3. Let destStart be pullIntoDescriptor’s byte offset + pullIntoDescriptor’s bytes filled.
  1379. auto dest_start = pull_into_descriptor.byte_offset + pull_into_descriptor.bytes_filled;
  1380. // 4. Assert: ! CanCopyDataBlockBytes(pullIntoDescriptor’s buffer, destStart, headOfQueue’s buffer, headOfQueue’s byte offset, bytesToCopy) is true.
  1381. VERIFY(can_copy_data_block_bytes_buffer(pull_into_descriptor.buffer, dest_start, head_of_queue.buffer, head_of_queue.byte_offset, bytes_to_copy));
  1382. // 5. Perform ! CopyDataBlockBytes(pullIntoDescriptor’s buffer.[[ArrayBufferData]], destStart, headOfQueue’s buffer.[[ArrayBufferData]], headOfQueue’s byte offset, bytesToCopy).
  1383. JS::copy_data_block_bytes(pull_into_descriptor.buffer->buffer(), dest_start, head_of_queue.buffer->buffer(), head_of_queue.byte_offset, bytes_to_copy);
  1384. // 6. If headOfQueue’s byte length is bytesToCopy,
  1385. if (head_of_queue.byte_length == bytes_to_copy) {
  1386. // 1. Remove queue[0].
  1387. queue.take_first();
  1388. }
  1389. // 7. Otherwise,
  1390. else {
  1391. // 1. Set headOfQueue’s byte offset to headOfQueue’s byte offset + bytesToCopy.
  1392. head_of_queue.byte_offset += bytes_to_copy;
  1393. // 2. Set headOfQueue’s byte length to headOfQueue’s byte length − bytesToCopy.
  1394. head_of_queue.byte_length -= bytes_to_copy;
  1395. }
  1396. // 8. Set controller.[[queueTotalSize]] to controller.[[queueTotalSize]] − bytesToCopy.
  1397. controller.set_queue_total_size(controller.queue_total_size() - bytes_to_copy);
  1398. // 9, Perform ! ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesToCopy, pullIntoDescriptor).
  1399. readable_byte_stream_controller_fill_head_pull_into_descriptor(controller, bytes_to_copy, pull_into_descriptor);
  1400. // 10. Set totalBytesToCopyRemaining to totalBytesToCopyRemaining − bytesToCopy.
  1401. total_bytes_to_copy_remaining -= bytes_to_copy;
  1402. }
  1403. // 12. If ready is false,
  1404. if (!ready) {
  1405. // 1. Assert: controller.[[queueTotalSize]] is 0.
  1406. VERIFY(controller.queue_total_size() == 0);
  1407. // 2. Assert: pullIntoDescriptor’s bytes filled > 0.
  1408. VERIFY(pull_into_descriptor.bytes_filled > 0);
  1409. // 3. Assert: pullIntoDescriptor’s bytes filled < pullIntoDescriptor’s minimum fill.
  1410. VERIFY(pull_into_descriptor.bytes_filled < pull_into_descriptor.minimum_fill);
  1411. }
  1412. // 13. Return ready.
  1413. return ready;
  1414. }
  1415. // https://streams.spec.whatwg.org/#readable-stream-default-reader-read
  1416. void readable_stream_default_reader_read(ReadableStreamDefaultReader& reader, ReadRequest& read_request)
  1417. {
  1418. // 1. Let stream be reader.[[stream]].
  1419. auto stream = reader.stream();
  1420. // 2. Assert: stream is not undefined.
  1421. VERIFY(stream);
  1422. // 3. Set stream.[[disturbed]] to true.
  1423. stream->set_disturbed(true);
  1424. // 4. If stream.[[state]] is "closed", perform readRequest’s close steps.
  1425. if (stream->is_closed()) {
  1426. read_request.on_close();
  1427. }
  1428. // 5. Otherwise, if stream.[[state]] is "errored", perform readRequest’s error steps given stream.[[storedError]].
  1429. else if (stream->is_errored()) {
  1430. read_request.on_error(stream->stored_error());
  1431. }
  1432. // 6. Otherwise,
  1433. else {
  1434. // 1. Assert: stream.[[state]] is "readable".
  1435. VERIFY(stream->is_readable());
  1436. // 2. Perform ! stream.[[controller]].[[PullSteps]](readRequest).
  1437. stream->controller()->visit([&](auto const& controller) {
  1438. return controller->pull_steps(read_request);
  1439. });
  1440. }
  1441. }
  1442. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-convert-pull-into-descriptor
  1443. JS::Value readable_byte_stream_controller_convert_pull_into_descriptor(JS::Realm& realm, PullIntoDescriptor const& pull_into_descriptor)
  1444. {
  1445. auto& vm = realm.vm();
  1446. // 1. Let bytesFilled be pullIntoDescriptor’s bytes filled.
  1447. auto bytes_filled = pull_into_descriptor.bytes_filled;
  1448. // 2. Let elementSize be pullIntoDescriptor’s element size.
  1449. auto element_size = pull_into_descriptor.element_size;
  1450. // 3. Assert: bytesFilled ≤ pullIntoDescriptor’s byte length.
  1451. VERIFY(bytes_filled <= pull_into_descriptor.byte_length);
  1452. // 4. Assert: the remainder after dividing bytesFilled by elementSize is 0.
  1453. VERIFY(bytes_filled % element_size == 0);
  1454. // 5. Let buffer be ! TransferArrayBuffer(pullIntoDescriptor’s buffer).
  1455. auto buffer = MUST(transfer_array_buffer(realm, pull_into_descriptor.buffer));
  1456. // 6. Return ! Construct(pullIntoDescriptor’s view constructor, « buffer, pullIntoDescriptor’s byte offset, bytesFilled ÷ elementSize »).
  1457. return MUST(JS::construct(vm, *pull_into_descriptor.view_constructor, buffer, JS::Value(pull_into_descriptor.byte_offset), JS::Value(bytes_filled / element_size)));
  1458. }
  1459. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-pull-into
  1460. void readable_byte_stream_controller_pull_into(ReadableByteStreamController& controller, WebIDL::ArrayBufferView& view, u64 min, ReadIntoRequest& read_into_request)
  1461. {
  1462. auto& vm = controller.vm();
  1463. auto& realm = controller.realm();
  1464. // 1. Let stream be controller.[[stream]].
  1465. auto stream = controller.stream();
  1466. // 2. Let elementSize be 1.
  1467. size_t element_size = 1;
  1468. // 3. Let ctor be %DataView%.
  1469. JS::NativeFunction* ctor = realm.intrinsics().data_view_constructor();
  1470. // 4. If view has a [[TypedArrayName]] internal slot (i.e., it is not a DataView),
  1471. if (view.bufferable_object().has<GC::Ref<JS::TypedArrayBase>>()) {
  1472. auto const& typed_array = *view.bufferable_object().get<GC::Ref<JS::TypedArrayBase>>();
  1473. // 1. Set elementSize to the element size specified in the typed array constructors table for view.[[TypedArrayName]].
  1474. element_size = typed_array.element_size();
  1475. // 2. Set ctor to the constructor specified in the typed array constructors table for view.[[TypedArrayName]].
  1476. switch (typed_array.kind()) {
  1477. #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, Type) \
  1478. case JS::TypedArrayBase::Kind::ClassName: \
  1479. ctor = realm.intrinsics().snake_name##_constructor(); \
  1480. break;
  1481. JS_ENUMERATE_TYPED_ARRAYS
  1482. #undef __JS_ENUMERATE
  1483. }
  1484. }
  1485. // 5. Let minimumFill be min × elementSize.
  1486. u64 minimum_fill = min * element_size;
  1487. // 6. Assert: minimumFill ≥ 0 and minimumFill ≤ view.[[ByteLength]].
  1488. VERIFY(minimum_fill <= view.byte_length());
  1489. // 7. Assert: the remainder after dividing minimumFill by elementSize is 0.
  1490. VERIFY(minimum_fill % element_size == 0);
  1491. // 8. Let byteOffset be view.[[ByteOffset]].
  1492. auto byte_offset = view.byte_offset();
  1493. // 6. Let byteLength be view.[[ByteLength]].
  1494. auto byte_length = view.byte_length();
  1495. // 7. Let bufferResult be TransferArrayBuffer(view.[[ViewedArrayBuffer]]).
  1496. auto buffer_result = transfer_array_buffer(realm, *view.viewed_array_buffer());
  1497. // 8. If bufferResult is an abrupt completion,
  1498. if (buffer_result.is_exception()) {
  1499. // 1. Perform readIntoRequest’s error steps, given bufferResult.[[Value]].
  1500. auto throw_completion = Bindings::exception_to_throw_completion(vm, buffer_result.exception());
  1501. read_into_request.on_error(*throw_completion.release_value());
  1502. // 2. Return.
  1503. return;
  1504. }
  1505. // 9. Let buffer be bufferResult.[[Value]].
  1506. auto buffer = buffer_result.value();
  1507. // 10. Let pullIntoDescriptor be a new pull-into descriptor with buffer buffer, buffer byte length buffer.[[ArrayBufferByteLength]],
  1508. // byte offset byteOffset, byte length byteLength, bytes filled 0, element size elementSize, view constructor ctor, and reader type "byob".
  1509. PullIntoDescriptor pull_into_descriptor {
  1510. .buffer = buffer,
  1511. .buffer_byte_length = buffer->byte_length(),
  1512. .byte_offset = byte_offset,
  1513. .byte_length = byte_length,
  1514. .bytes_filled = 0,
  1515. .minimum_fill = minimum_fill,
  1516. .element_size = element_size,
  1517. .view_constructor = *ctor,
  1518. .reader_type = ReaderType::Byob,
  1519. };
  1520. // 11. If controller.[[pendingPullIntos]] is not empty,
  1521. if (!controller.pending_pull_intos().is_empty()) {
  1522. // 1. Append pullIntoDescriptor to controller.[[pendingPullIntos]].
  1523. controller.pending_pull_intos().append(pull_into_descriptor);
  1524. // 2. Perform ! ReadableStreamAddReadIntoRequest(stream, readIntoRequest).
  1525. readable_stream_add_read_into_request(*stream, read_into_request);
  1526. // 3. Return.
  1527. return;
  1528. }
  1529. // 12. If stream.[[state]] is "closed",
  1530. if (stream->is_closed()) {
  1531. // 1. Let emptyView be ! Construct(ctor, « pullIntoDescriptor’s buffer, pullIntoDescriptor’s byte offset, 0 »).
  1532. auto empty_view = MUST(JS::construct(vm, *ctor, pull_into_descriptor.buffer, JS::Value(pull_into_descriptor.byte_offset), JS::Value(0)));
  1533. // 2. Perform readIntoRequest’s close steps, given emptyView.
  1534. read_into_request.on_close(empty_view);
  1535. // 3. Return.
  1536. return;
  1537. }
  1538. // 13. If controller.[[queueTotalSize]] > 0,
  1539. if (controller.queue_total_size() > 0) {
  1540. // 1. If ! ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) is true,
  1541. if (readable_byte_stream_controller_fill_pull_into_descriptor_from_queue(controller, pull_into_descriptor)) {
  1542. // 1. Let filledView be ! ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor).
  1543. auto filled_view = readable_byte_stream_controller_convert_pull_into_descriptor(realm, pull_into_descriptor);
  1544. // 2. Perform ! ReadableByteStreamControllerHandleQueueDrain(controller).
  1545. readable_byte_stream_controller_handle_queue_drain(controller);
  1546. // 3. Perform readIntoRequest’s chunk steps, given filledView.
  1547. read_into_request.on_chunk(filled_view);
  1548. // 4. Return.
  1549. return;
  1550. }
  1551. // 2. If controller.[[closeRequested]] is true,
  1552. if (controller.close_requested()) {
  1553. // 1. Let e be a TypeError exception.
  1554. auto error = JS::TypeError::create(realm, "Reader has been released"sv);
  1555. // 2. Perform ! ReadableByteStreamControllerError(controller, e).
  1556. readable_byte_stream_controller_error(controller, error);
  1557. // 3. Perform readIntoRequest’s error steps, given e.
  1558. read_into_request.on_error(error);
  1559. // 4. Return.
  1560. return;
  1561. }
  1562. }
  1563. // 14. Append pullIntoDescriptor to controller.[[pendingPullIntos]].
  1564. controller.pending_pull_intos().append(pull_into_descriptor);
  1565. // 15. Perform ! ReadableStreamAddReadIntoRequest(stream, readIntoRequest).
  1566. readable_stream_add_read_into_request(*stream, read_into_request);
  1567. // 16. Perform ! ReadableByteStreamControllerCallPullIfNeeded(controller).
  1568. readable_byte_stream_controller_call_pull_if_needed(controller);
  1569. }
  1570. // https://streams.spec.whatwg.org/#readable-stream-byob-reader-read
  1571. void readable_stream_byob_reader_read(ReadableStreamBYOBReader& reader, WebIDL::ArrayBufferView& view, u64 min, ReadIntoRequest& read_into_request)
  1572. {
  1573. // 1. Let stream be reader.[[stream]].
  1574. auto stream = reader.stream();
  1575. // 2. Assert: stream is not undefined.
  1576. VERIFY(stream);
  1577. // 3. Set stream.[[disturbed]] to true.
  1578. stream->set_disturbed(true);
  1579. // 4. If stream.[[state]] is "errored", perform readIntoRequest’s error steps given stream.[[storedError]].
  1580. if (stream->is_errored()) {
  1581. read_into_request.on_error(stream->stored_error());
  1582. }
  1583. // 5. Otherwise, perform ! ReadableByteStreamControllerPullInto(stream.[[controller]], view, readIntoRequest).
  1584. else {
  1585. readable_byte_stream_controller_pull_into(*stream->controller()->get<GC::Ref<ReadableByteStreamController>>(), view, min, read_into_request);
  1586. }
  1587. }
  1588. // https://streams.spec.whatwg.org/#abstract-opdef-readablestreamdefaultreaderrelease
  1589. void readable_stream_default_reader_release(ReadableStreamDefaultReader& reader)
  1590. {
  1591. auto& realm = reader.realm();
  1592. // 1. Perform ! ReadableStreamReaderGenericRelease(reader).
  1593. readable_stream_reader_generic_release(reader);
  1594. // 2. Let e be a new TypeError exception.
  1595. auto exception = JS::TypeError::create(realm, "Reader has been released"sv);
  1596. // 3. Perform ! ReadableStreamDefaultReaderErrorReadRequests(reader, e).
  1597. readable_stream_default_reader_error_read_requests(reader, exception);
  1598. }
  1599. // https://streams.spec.whatwg.org/#abstract-opdef-readablestreambyobreaderrelease
  1600. void readable_stream_byob_reader_release(ReadableStreamBYOBReader& reader)
  1601. {
  1602. auto& realm = reader.realm();
  1603. // 1. Perform ! ReadableStreamReaderGenericRelease(reader).
  1604. readable_stream_reader_generic_release(reader);
  1605. // 2. Let e be a new TypeError exception.
  1606. auto exception = JS::TypeError::create(realm, "Reader has been released"sv);
  1607. // 3. Perform ! ReadableStreamBYOBReaderErrorReadIntoRequests(reader, e).
  1608. readable_stream_byob_reader_error_read_into_requests(reader, exception);
  1609. }
  1610. // https://streams.spec.whatwg.org/#set-up-readable-stream-default-reader
  1611. WebIDL::ExceptionOr<void> set_up_readable_stream_default_reader(ReadableStreamDefaultReader& reader, ReadableStream& stream)
  1612. {
  1613. // 1. If ! IsReadableStreamLocked(stream) is true, throw a TypeError exception.
  1614. if (is_readable_stream_locked(stream))
  1615. return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Cannot create stream reader for a locked stream"sv };
  1616. // 2. Perform ! ReadableStreamReaderGenericInitialize(reader, stream).
  1617. // 3. Set reader.[[readRequests]] to a new empty list.
  1618. readable_stream_reader_generic_initialize(ReadableStreamReader { reader }, stream);
  1619. return {};
  1620. }
  1621. // https://streams.spec.whatwg.org/#set-up-readable-stream-byob-reader
  1622. WebIDL::ExceptionOr<void> set_up_readable_stream_byob_reader(ReadableStreamBYOBReader& reader, ReadableStream& stream)
  1623. {
  1624. // 1. If ! IsReadableStreamLocked(stream) is true, throw a TypeError exception.
  1625. if (is_readable_stream_locked(stream))
  1626. return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Cannot create stream reader for a locked stream"sv };
  1627. // 2. If stream.[[controller]] does not implement ReadableByteStreamController, throw a TypeError exception.
  1628. if (!stream.controller()->has<GC::Ref<ReadableByteStreamController>>())
  1629. return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "BYOB reader cannot set up reader from non-byte stream"sv };
  1630. // 3. Perform ! ReadableStreamReaderGenericInitialize(reader, stream).
  1631. readable_stream_reader_generic_initialize(ReadableStreamReader { reader }, stream);
  1632. // 4. Set reader.[[readIntoRequests]] to a new empty list.
  1633. reader.read_into_requests().clear();
  1634. return {};
  1635. }
  1636. // https://streams.spec.whatwg.org/#readable-stream-default-controller-close
  1637. void readable_stream_default_controller_close(ReadableStreamDefaultController& controller)
  1638. {
  1639. // 1. If ! ReadableStreamDefaultControllerCanCloseOrEnqueue(controller) is false, return.
  1640. if (!readable_stream_default_controller_can_close_or_enqueue(controller))
  1641. return;
  1642. // 2. Let stream be controller.[[stream]].
  1643. auto stream = controller.stream();
  1644. // 3. Set controller.[[closeRequested]] to true.
  1645. controller.set_close_requested(true);
  1646. // 4. If controller.[[queue]] is empty,
  1647. if (controller.queue().is_empty()) {
  1648. // 1. Perform ! ReadableStreamDefaultControllerClearAlgorithms(controller).
  1649. readable_stream_default_controller_clear_algorithms(controller);
  1650. // 2. Perform ! ReadableStreamClose(stream).
  1651. readable_stream_close(*stream);
  1652. }
  1653. }
  1654. // https://streams.spec.whatwg.org/#rs-default-controller-has-backpressure
  1655. bool readable_stream_default_controller_has_backpressure(ReadableStreamDefaultController& controller)
  1656. {
  1657. // 1. If ! ReadableStreamDefaultControllerShouldCallPull(controller) is true, return false.
  1658. if (readable_stream_default_controller_should_call_pull(controller))
  1659. return false;
  1660. // 2. Otherwise, return true.
  1661. return true;
  1662. }
  1663. // https://streams.spec.whatwg.org/#readable-stream-default-controller-enqueue
  1664. WebIDL::ExceptionOr<void> readable_stream_default_controller_enqueue(ReadableStreamDefaultController& controller, JS::Value chunk)
  1665. {
  1666. auto& vm = controller.vm();
  1667. // 1. If ! ReadableStreamDefaultControllerCanCloseOrEnqueue(controller) is false, return.
  1668. if (!readable_stream_default_controller_can_close_or_enqueue(controller))
  1669. return {};
  1670. // 2. Let stream be controller.[[stream]].
  1671. auto stream = controller.stream();
  1672. // 3. If ! IsReadableStreamLocked(stream) is true and ! ReadableStreamGetNumReadRequests(stream) > 0, perform ! ReadableStreamFulfillReadRequest(stream, chunk, false).
  1673. if (is_readable_stream_locked(*stream) && readable_stream_get_num_read_requests(*stream) > 0) {
  1674. readable_stream_fulfill_read_request(*stream, chunk, false);
  1675. }
  1676. // 4. Otherwise,
  1677. else {
  1678. // 1. Let result be the result of performing controller.[[strategySizeAlgorithm]], passing in chunk, and interpreting the result as a completion record.
  1679. auto result = controller.strategy_size_algorithm()->function()(chunk);
  1680. // 2. If result is an abrupt completion,
  1681. if (result.is_abrupt()) {
  1682. // 1. Perform ! ReadableStreamDefaultControllerError(controller, result.[[Value]]).
  1683. readable_stream_default_controller_error(controller, result.value().value());
  1684. // 2. Return result.
  1685. return result;
  1686. }
  1687. // 3. Let chunkSize be result.[[Value]].
  1688. auto chunk_size = result.release_value().release_value();
  1689. // 4. Let enqueueResult be EnqueueValueWithSize(controller, chunk, chunkSize).
  1690. auto enqueue_result = enqueue_value_with_size(controller, chunk, chunk_size);
  1691. // 5. If enqueueResult is an abrupt completion,
  1692. if (enqueue_result.is_error()) {
  1693. auto throw_completion = Bindings::throw_dom_exception_if_needed(vm, [&] { return enqueue_result; }).throw_completion();
  1694. // 1. Perform ! ReadableStreamDefaultControllerError(controller, enqueueResult.[[Value]]).
  1695. readable_stream_default_controller_error(controller, throw_completion.value().value());
  1696. // 2. Return enqueueResult.
  1697. // Note: We need to return the throw_completion object here, as enqueue needs to throw the same object that the controller is errored with
  1698. return throw_completion;
  1699. }
  1700. }
  1701. // 5. Perform ! ReadableStreamDefaultControllerCallPullIfNeeded(controller).
  1702. readable_stream_default_controller_can_pull_if_needed(controller);
  1703. return {};
  1704. }
  1705. // https://streams.spec.whatwg.org/#readable-stream-default-controller-call-pull-if-needed
  1706. void readable_stream_default_controller_can_pull_if_needed(ReadableStreamDefaultController& controller)
  1707. {
  1708. // 1. Let shouldPull be ! ReadableStreamDefaultControllerShouldCallPull(controller).
  1709. auto should_pull = readable_stream_default_controller_should_call_pull(controller);
  1710. // 2. If shouldPull is false, return.
  1711. if (!should_pull)
  1712. return;
  1713. // 3. If controller.[[pulling]] is true,
  1714. if (controller.pulling()) {
  1715. // 1. Set controller.[[pullAgain]] to true.
  1716. controller.set_pull_again(true);
  1717. // 2. Return.
  1718. return;
  1719. }
  1720. // 4. Assert: controller.[[pullAgain]] is false.
  1721. VERIFY(!controller.pull_again());
  1722. // 5. Set controller.[[pulling]] to true.
  1723. controller.set_pulling(true);
  1724. // 6. Let pullPromise be the result of performing controller.[[pullAlgorithm]].
  1725. auto pull_promise = controller.pull_algorithm()->function()();
  1726. // 7. Upon fulfillment of pullPromise,
  1727. WebIDL::upon_fulfillment(*pull_promise, GC::create_function(controller.heap(), [&controller](JS::Value) -> WebIDL::ExceptionOr<JS::Value> {
  1728. // 1. Set controller.[[pulling]] to false.
  1729. controller.set_pulling(false);
  1730. // 2. If controller.[[pullAgain]] is true,
  1731. if (controller.pull_again()) {
  1732. // 1. Set controller.[[pullAgain]] to false.
  1733. controller.set_pull_again(false);
  1734. // 2. Perform ! ReadableStreamDefaultControllerCallPullIfNeeded(controller).
  1735. readable_stream_default_controller_can_pull_if_needed(controller);
  1736. }
  1737. return JS::js_undefined();
  1738. }));
  1739. // 8. Upon rejection of pullPromise with reason e,
  1740. WebIDL::upon_rejection(*pull_promise, GC::create_function(controller.heap(), [&controller](JS::Value e) -> WebIDL::ExceptionOr<JS::Value> {
  1741. // 1. Perform ! ReadableStreamDefaultControllerError(controller, e).
  1742. readable_stream_default_controller_error(controller, e);
  1743. return JS::js_undefined();
  1744. }));
  1745. }
  1746. // https://streams.spec.whatwg.org/#readable-stream-default-controller-should-call-pull
  1747. bool readable_stream_default_controller_should_call_pull(ReadableStreamDefaultController& controller)
  1748. {
  1749. // 1. Let stream be controller.[[stream]].
  1750. auto stream = controller.stream();
  1751. // 2. If ! ReadableStreamDefaultControllerCanCloseOrEnqueue(controller) is false, return false.
  1752. if (!readable_stream_default_controller_can_close_or_enqueue(controller))
  1753. return false;
  1754. // 3. If controller.[[started]] is false, return false.
  1755. if (!controller.started())
  1756. return false;
  1757. // 4. If ! IsReadableStreamLocked(stream) is true and ! ReadableStreamGetNumReadRequests(stream) > 0, return true.
  1758. if (is_readable_stream_locked(*stream) && readable_stream_get_num_read_requests(*stream) > 0)
  1759. return true;
  1760. // 5. Let desiredSize be ! ReadableStreamDefaultControllerGetDesiredSize(controller).
  1761. auto desired_size = readable_stream_default_controller_get_desired_size(controller);
  1762. // 6. Assert: desiredSize is not null.
  1763. VERIFY(desired_size.has_value());
  1764. // 7. If desiredSize > 0, return true.
  1765. if (desired_size.release_value() > 0.0)
  1766. return true;
  1767. // 8. Return false.
  1768. return false;
  1769. }
  1770. // https://streams.spec.whatwg.org/#abstract-opdef-readablebytestreamcontrollergetbyobrequest
  1771. GC::Ptr<ReadableStreamBYOBRequest> readable_byte_stream_controller_get_byob_request(GC::Ref<ReadableByteStreamController> controller)
  1772. {
  1773. auto& vm = controller->vm();
  1774. auto& realm = controller->realm();
  1775. // 1. If controller.[[byobRequest]] is null and controller.[[pendingPullIntos]] is not empty,
  1776. if (!controller->raw_byob_request() && !controller->pending_pull_intos().is_empty()) {
  1777. // 1. Let firstDescriptor be controller.[[pendingPullIntos]][0].
  1778. auto const& first_descriptor = controller->pending_pull_intos().first();
  1779. // 2. Let view be ! Construct(%Uint8Array%, « firstDescriptor’s buffer, firstDescriptor’s byte offset + firstDescriptor’s bytes filled, firstDescriptor’s byte length − firstDescriptor’s bytes filled »).
  1780. auto view = MUST(JS::construct(vm, *realm.intrinsics().uint8_array_constructor(), first_descriptor.buffer, JS::Value(first_descriptor.byte_offset + first_descriptor.bytes_filled), JS::Value(first_descriptor.byte_length - first_descriptor.bytes_filled)));
  1781. // 3. Let byobRequest be a new ReadableStreamBYOBRequest.
  1782. auto byob_request = realm.create<ReadableStreamBYOBRequest>(realm);
  1783. // 4. Set byobRequest.[[controller]] to controller.
  1784. byob_request->set_controller(controller);
  1785. // 5. Set byobRequest.[[view]] to view.
  1786. auto array_buffer_view = realm.create<WebIDL::ArrayBufferView>(view);
  1787. byob_request->set_view(array_buffer_view);
  1788. // 6. Set controller.[[byobRequest]] to byobRequest.
  1789. controller->set_byob_request(byob_request);
  1790. }
  1791. // 2. Return controller.[[byobRequest]].
  1792. return controller->raw_byob_request();
  1793. }
  1794. // https://streams.spec.whatwg.org/#readable-stream-default-controller-clear-algorithms
  1795. void readable_stream_default_controller_clear_algorithms(ReadableStreamDefaultController& controller)
  1796. {
  1797. // 1. Set controller.[[pullAlgorithm]] to undefined.
  1798. controller.set_pull_algorithm({});
  1799. // 2. Set controller.[[cancelAlgorithm]] to undefined.
  1800. controller.set_cancel_algorithm({});
  1801. // 3. Set controller.[[strategySizeAlgorithm]] to undefined.
  1802. controller.set_strategy_size_algorithm({});
  1803. }
  1804. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-respond-in-readable-state
  1805. WebIDL::ExceptionOr<void> readable_byte_stream_controller_respond_in_readable_state(ReadableByteStreamController& controller, u64 bytes_written, PullIntoDescriptor& pull_into_descriptor)
  1806. {
  1807. // 1. Assert: pullIntoDescriptor’s bytes filled + bytesWritten ≤ pullIntoDescriptor’s byte length.
  1808. VERIFY(pull_into_descriptor.bytes_filled + bytes_written <= pull_into_descriptor.byte_length);
  1809. // 2. Perform ! ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesWritten, pullIntoDescriptor).
  1810. readable_byte_stream_controller_fill_head_pull_into_descriptor(controller, bytes_written, pull_into_descriptor);
  1811. // 3. If pullIntoDescriptor’s reader type is "none",
  1812. if (pull_into_descriptor.reader_type == ReaderType::None) {
  1813. // 1. Perform ? ReadableByteStreamControllerEnqueueDetachedPullIntoToQueue(controller, pullIntoDescriptor).
  1814. TRY(readable_byte_stream_controller_enqueue_detached_pull_into_queue(controller, pull_into_descriptor));
  1815. // 2. Let filledPullIntos be the result of performing ! ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller).
  1816. auto filled_pulled_intos = readable_byte_stream_controller_process_pull_into_descriptors_using_queue(controller);
  1817. // 3. For each filledPullInto of filledPullIntos,
  1818. for (auto& filled_pull_into : filled_pulled_intos) {
  1819. // 1. Perform ! ReadableByteStreamControllerCommitPullIntoDescriptor(controller.[[stream]], filledPullInto).
  1820. readable_byte_stream_controller_commit_pull_into_descriptor(*controller.stream(), filled_pull_into);
  1821. }
  1822. // 4. Return.
  1823. return {};
  1824. }
  1825. // 4. If pullIntoDescriptor’s bytes filled < pullIntoDescriptor’s minimum fill, return.
  1826. if (pull_into_descriptor.bytes_filled < pull_into_descriptor.minimum_fill)
  1827. return {};
  1828. // NOTE: A descriptor for a read() request that is not yet filled up to its minimum length will stay at the head of the queue, so the underlying source can keep filling it.
  1829. // 5. Perform ! ReadableByteStreamControllerShiftPendingPullInto(controller).
  1830. // NOTE: We need to take a copy of pull_into_descriptor here as the shift destroys the pull into descriptor we are given.
  1831. auto pull_into_descriptor_copy = readable_byte_stream_controller_shift_pending_pull_into(controller);
  1832. // 6. Let remainderSize be the remainder after dividing pullIntoDescriptor’s bytes filled by pullIntoDescriptor’s element size.
  1833. auto remainder_size = pull_into_descriptor_copy.bytes_filled % pull_into_descriptor_copy.element_size;
  1834. // 7. If remainderSize > 0,
  1835. if (remainder_size > 0) {
  1836. // 1. Let end be pullIntoDescriptor’s byte offset + pullIntoDescriptor’s bytes filled.
  1837. auto end = pull_into_descriptor_copy.byte_offset + pull_into_descriptor_copy.bytes_filled;
  1838. // 2. Perform ? ReadableByteStreamControllerEnqueueClonedChunkToQueue(controller, pullIntoDescriptor’s buffer, end − remainderSize, remainderSize).
  1839. TRY(readable_byte_stream_controller_enqueue_cloned_chunk_to_queue(controller, *pull_into_descriptor_copy.buffer, end - remainder_size, remainder_size));
  1840. }
  1841. // 8. Set pullIntoDescriptor’s bytes filled to pullIntoDescriptor’s bytes filled − remainderSize.
  1842. pull_into_descriptor_copy.bytes_filled -= remainder_size;
  1843. // 9. Let filledPullIntos be the result of performing ! ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller).
  1844. auto filled_pulled_intos = readable_byte_stream_controller_process_pull_into_descriptors_using_queue(controller);
  1845. // 10. Perform ! ReadableByteStreamControllerCommitPullIntoDescriptor(controller.[[stream]], pullIntoDescriptor).
  1846. readable_byte_stream_controller_commit_pull_into_descriptor(*controller.stream(), pull_into_descriptor_copy);
  1847. // 11. For each filledPullInto of filledPullIntos,
  1848. for (auto& filled_pull_into : filled_pulled_intos) {
  1849. // 1. Perform ! ReadableByteStreamControllerCommitPullIntoDescriptor(controller.[[stream]], filledPullInto).
  1850. readable_byte_stream_controller_commit_pull_into_descriptor(*controller.stream(), filled_pull_into);
  1851. }
  1852. return {};
  1853. }
  1854. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-respond-in-closed-state
  1855. void readable_byte_stream_controller_respond_in_closed_state(ReadableByteStreamController& controller, PullIntoDescriptor& first_descriptor)
  1856. {
  1857. // 1. Assert: the remainder after dividing firstDescriptor’s bytes filled by firstDescriptor’s element size is 0.
  1858. VERIFY(first_descriptor.bytes_filled % first_descriptor.element_size == 0);
  1859. // 2. If firstDescriptor’s reader type is "none", perform ! ReadableByteStreamControllerShiftPendingPullInto(controller).
  1860. if (first_descriptor.reader_type == ReaderType::None)
  1861. readable_byte_stream_controller_shift_pending_pull_into(controller);
  1862. // 3. Let stream be controller.[[stream]].
  1863. auto& stream = *controller.stream();
  1864. // 4. If ! ReadableStreamHasBYOBReader(stream) is true,
  1865. if (readable_stream_has_byob_reader(stream)) {
  1866. // 1. Let filledPullIntos be a new empty list.
  1867. SinglyLinkedList<PullIntoDescriptor> filled_pull_intos;
  1868. // 2. Let i be 0.
  1869. u64 i = 0;
  1870. // 1. While i < ! ReadableStreamGetNumReadIntoRequests(stream),
  1871. while (i < readable_stream_get_num_read_into_requests(stream)) {
  1872. // 1. Let pullIntoDescriptor be ! ReadableByteStreamControllerShiftPendingPullInto(controller).
  1873. auto pull_into_descriptor = readable_byte_stream_controller_shift_pending_pull_into(controller);
  1874. // 2. Append pullIntoDescriptor to filledPullIntos.
  1875. filled_pull_intos.append(pull_into_descriptor);
  1876. // 3. Set i to i + 1.
  1877. i++;
  1878. // 4. For each filledPullInto of filledPullIntos,
  1879. for (auto& filled_pull_into : filled_pull_intos) {
  1880. // 1. Perform ! ReadableByteStreamControllerCommitPullIntoDescriptor(stream, filledPullInto).
  1881. readable_byte_stream_controller_commit_pull_into_descriptor(stream, filled_pull_into);
  1882. }
  1883. }
  1884. }
  1885. }
  1886. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-respond-internal
  1887. WebIDL::ExceptionOr<void> readable_byte_stream_controller_respond_internal(ReadableByteStreamController& controller, u64 bytes_written)
  1888. {
  1889. // 1. Let firstDescriptor be controller.[[pendingPullIntos]][0].
  1890. auto& first_descriptor = controller.pending_pull_intos().first();
  1891. // 2. Assert: ! CanTransferArrayBuffer(firstDescriptor’s buffer) is true.
  1892. VERIFY(can_transfer_array_buffer(*first_descriptor.buffer));
  1893. // 3. Perform ! ReadableByteStreamControllerInvalidateBYOBRequest(controller).
  1894. readable_byte_stream_controller_invalidate_byob_request(controller);
  1895. // 4. Let state be controller.[[stream]].[[state]].
  1896. auto state = controller.stream()->state();
  1897. // 5. If state is "closed",
  1898. if (state == ReadableStream::State::Closed) {
  1899. // 1. Assert: bytesWritten is 0.
  1900. VERIFY(bytes_written == 0);
  1901. // 2. Perform ! ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor).
  1902. readable_byte_stream_controller_respond_in_closed_state(controller, first_descriptor);
  1903. }
  1904. // 6. Otherwise,
  1905. else {
  1906. // 1. Assert: state is "readable".
  1907. VERIFY(state == ReadableStream::State::Readable);
  1908. // 2. Assert: bytesWritten > 0.
  1909. VERIFY(bytes_written > 0);
  1910. // 3. Perform ? ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, firstDescriptor).
  1911. TRY(readable_byte_stream_controller_respond_in_readable_state(controller, bytes_written, first_descriptor));
  1912. }
  1913. // 7. Perform ! ReadableByteStreamControllerCallPullIfNeeded(controller).
  1914. readable_byte_stream_controller_call_pull_if_needed(controller);
  1915. return {};
  1916. }
  1917. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-respond
  1918. WebIDL::ExceptionOr<void> readable_byte_stream_controller_respond(ReadableByteStreamController& controller, u64 bytes_written)
  1919. {
  1920. auto& realm = controller.realm();
  1921. // 1. Assert: controller.[[pendingPullIntos]] is not empty.
  1922. VERIFY(!controller.pending_pull_intos().is_empty());
  1923. // 2. Let firstDescriptor be controller.[[pendingPullIntos]][0].
  1924. auto& first_descriptor = controller.pending_pull_intos().first();
  1925. // 3. Let state be controller.[[stream]].[[state]].
  1926. auto state = controller.stream()->state();
  1927. // 4. If state is "closed",
  1928. if (state == ReadableStream::State::Closed) {
  1929. // 1. If bytesWritten is not 0, throw a TypeError exception.
  1930. if (bytes_written != 0)
  1931. return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Bytes written is not zero for closed stream"sv };
  1932. }
  1933. // 5. Otherwise,
  1934. else {
  1935. // 1. Assert: state is "readable".
  1936. VERIFY(state == ReadableStream::State::Readable);
  1937. // 2. If bytesWritten is 0, throw a TypeError exception.
  1938. if (bytes_written == 0)
  1939. return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Bytes written is zero for stream which is not closed"sv };
  1940. // 3. If firstDescriptor’s bytes filled + bytesWritten > firstDescriptor’s byte length, throw a RangeError exception.
  1941. if (first_descriptor.bytes_filled + bytes_written > first_descriptor.byte_length)
  1942. return WebIDL::SimpleException { WebIDL::SimpleExceptionType::RangeError, "Bytes written is greater than the pull requests byte length"sv };
  1943. }
  1944. // 6. Set firstDescriptor’s buffer to ! TransferArrayBuffer(firstDescriptor’s buffer).
  1945. first_descriptor.buffer = MUST(transfer_array_buffer(realm, *first_descriptor.buffer));
  1946. // 7. Perform ? ReadableByteStreamControllerRespondInternal(controller, bytesWritten).
  1947. return readable_byte_stream_controller_respond_internal(controller, bytes_written);
  1948. }
  1949. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-respond-with-new-view
  1950. WebIDL::ExceptionOr<void> readable_byte_stream_controller_respond_with_new_view(JS::Realm& realm, ReadableByteStreamController& controller, WebIDL::ArrayBufferView& view)
  1951. {
  1952. // 1. Assert: controller.[[pendingPullIntos]] is not empty.
  1953. VERIFY(!controller.pending_pull_intos().is_empty());
  1954. // 2. Assert: ! IsDetachedBuffer(view.[[ViewedArrayBuffer]]) is false.
  1955. VERIFY(!view.viewed_array_buffer()->is_detached());
  1956. // 3. Let firstDescriptor be controller.[[pendingPullIntos]][0].
  1957. auto& first_descriptor = controller.pending_pull_intos().first();
  1958. // 4. Let state be controller.[[stream]].[[state]].
  1959. auto state = controller.stream()->state();
  1960. // 5. If state is "closed",
  1961. if (state == ReadableStream::State::Closed) {
  1962. // 1. If view.[[ByteLength]] is not 0, throw a TypeError exception.
  1963. if (view.byte_length() != 0)
  1964. return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Byte length is not zero for closed stream"sv };
  1965. }
  1966. // 6. Otherwise,
  1967. else {
  1968. // 1. Assert: state is "readable".
  1969. VERIFY(state == ReadableStream::State::Readable);
  1970. // 2. If view.[[ByteLength]] is 0, throw a TypeError exception.
  1971. if (view.byte_length() == 0)
  1972. return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Byte length is zero for stream which is not closed"sv };
  1973. }
  1974. // 7. If firstDescriptor’s byte offset + firstDescriptor’ bytes filled is not view.[[ByteOffset]], throw a RangeError exception.
  1975. if (first_descriptor.byte_offset + first_descriptor.bytes_filled != view.byte_offset())
  1976. return WebIDL::SimpleException { WebIDL::SimpleExceptionType::RangeError, "Byte offset is not aligned with the pull request's byte offset"sv };
  1977. // 8. If firstDescriptor’s buffer byte length is not view.[[ViewedArrayBuffer]].[[ByteLength]], throw a RangeError exception.
  1978. if (first_descriptor.buffer_byte_length != view.viewed_array_buffer()->byte_length())
  1979. return WebIDL::SimpleException { WebIDL::SimpleExceptionType::RangeError, "Buffer byte length is not aligned with the pull request's byte length"sv };
  1980. // 9. If firstDescriptor’s bytes filled + view.[[ByteLength]] > firstDescriptor’s byte length, throw a RangeError exception.
  1981. if (first_descriptor.bytes_filled + view.byte_length() > first_descriptor.byte_length)
  1982. return WebIDL::SimpleException { WebIDL::SimpleExceptionType::RangeError, "Byte length is greater than the pull request's byte length"sv };
  1983. // 10. Let viewByteLength be view.[[ByteLength]].
  1984. auto view_byte_length = view.byte_length();
  1985. // 11. Set firstDescriptor’s buffer to ? TransferArrayBuffer(view.[[ViewedArrayBuffer]]).
  1986. first_descriptor.buffer = TRY(transfer_array_buffer(realm, *view.viewed_array_buffer()));
  1987. // 12. Perform ? ReadableByteStreamControllerRespondInternal(controller, viewByteLength).
  1988. TRY(readable_byte_stream_controller_respond_internal(controller, view_byte_length));
  1989. return {};
  1990. }
  1991. // https://streams.spec.whatwg.org/#readable-stream-default-controller-error
  1992. void readable_stream_default_controller_error(ReadableStreamDefaultController& controller, JS::Value error)
  1993. {
  1994. // 1. Let stream be controller.[[stream]].
  1995. auto stream = controller.stream();
  1996. // 2. If stream.[[state]] is not "readable", return.
  1997. if (!stream->is_readable())
  1998. return;
  1999. // 3. Perform ! ResetQueue(controller).
  2000. reset_queue(controller);
  2001. // 4. Perform ! ReadableStreamDefaultControllerClearAlgorithms(controller).
  2002. readable_stream_default_controller_clear_algorithms(controller);
  2003. // 5. Perform ! ReadableStreamError(stream, e).
  2004. readable_stream_error(*stream, error);
  2005. }
  2006. // https://streams.spec.whatwg.org/#readable-stream-default-controller-get-desired-size
  2007. Optional<double> readable_stream_default_controller_get_desired_size(ReadableStreamDefaultController& controller)
  2008. {
  2009. auto stream = controller.stream();
  2010. // 1. Let state be controller.[[stream]].[[state]].
  2011. // 2. If state is "errored", return null.
  2012. if (stream->is_errored())
  2013. return {};
  2014. // 3. If state is "closed", return 0.
  2015. if (stream->is_closed())
  2016. return 0.0;
  2017. // 4. Return controller.[[strategyHWM]] − controller.[[queueTotalSize]].
  2018. return controller.strategy_hwm() - controller.queue_total_size();
  2019. }
  2020. // https://streams.spec.whatwg.org/#readable-stream-default-controller-can-close-or-enqueue
  2021. bool readable_stream_default_controller_can_close_or_enqueue(ReadableStreamDefaultController& controller)
  2022. {
  2023. // 1. Let state be controller.[[stream]].[[state]].
  2024. // 2. If controller.[[closeRequested]] is false and state is "readable", return true.
  2025. // 3. Otherwise, return false.
  2026. return !controller.close_requested() && controller.stream()->is_readable();
  2027. }
  2028. // https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller
  2029. WebIDL::ExceptionOr<void> set_up_readable_stream_default_controller(ReadableStream& stream, ReadableStreamDefaultController& controller, GC::Ref<StartAlgorithm> start_algorithm, GC::Ref<PullAlgorithm> pull_algorithm, GC::Ref<CancelAlgorithm> cancel_algorithm, double high_water_mark, GC::Ref<SizeAlgorithm> size_algorithm)
  2030. {
  2031. auto& realm = stream.realm();
  2032. // 1. Assert: stream.[[controller]] is undefined.
  2033. VERIFY(!stream.controller().has_value());
  2034. // 2. Set controller.[[stream]] to stream.
  2035. controller.set_stream(stream);
  2036. // 3. Perform ! ResetQueue(controller).
  2037. reset_queue(controller);
  2038. // 4. Set controller.[[started]], controller.[[closeRequested]], controller.[[pullAgain]], and controller.[[pulling]] to false.
  2039. controller.set_started(false);
  2040. controller.set_close_requested(false);
  2041. controller.set_pull_again(false);
  2042. controller.set_pulling(false);
  2043. // 5. Set controller.[[strategySizeAlgorithm]] to sizeAlgorithm and controller.[[strategyHWM]] to highWaterMark.
  2044. controller.set_strategy_size_algorithm(size_algorithm);
  2045. controller.set_strategy_hwm(high_water_mark);
  2046. // 6. Set controller.[[pullAlgorithm]] to pullAlgorithm.
  2047. controller.set_pull_algorithm(pull_algorithm);
  2048. // 7. Set controller.[[cancelAlgorithm]] to cancelAlgorithm.
  2049. controller.set_cancel_algorithm(cancel_algorithm);
  2050. // 8. Set stream.[[controller]] to controller.
  2051. stream.set_controller(ReadableStreamController { controller });
  2052. // 9. Let startResult be the result of performing startAlgorithm. (This might throw an exception.)
  2053. auto start_result = TRY(start_algorithm->function()());
  2054. // 10. Let startPromise be a promise resolved with startResult.
  2055. auto start_promise = WebIDL::create_resolved_promise(realm, start_result);
  2056. // 11. Upon fulfillment of startPromise,
  2057. WebIDL::upon_fulfillment(start_promise, GC::create_function(controller.heap(), [&controller](JS::Value) -> WebIDL::ExceptionOr<JS::Value> {
  2058. // 1. Set controller.[[started]] to true.
  2059. controller.set_started(true);
  2060. // 2. Assert: controller.[[pulling]] is false.
  2061. VERIFY(!controller.pulling());
  2062. // 3. Assert: controller.[[pullAgain]] is false.
  2063. VERIFY(!controller.pull_again());
  2064. // 4. Perform ! ReadableStreamDefaultControllerCallPullIfNeeded(controller).
  2065. readable_stream_default_controller_can_pull_if_needed(controller);
  2066. return JS::js_undefined();
  2067. }));
  2068. // 12. Upon rejection of startPromise with reason r,
  2069. WebIDL::upon_rejection(start_promise, GC::create_function(controller.heap(), [&controller](JS::Value r) -> WebIDL::ExceptionOr<JS::Value> {
  2070. // 1. Perform ! ReadableStreamDefaultControllerError(controller, r).
  2071. readable_stream_default_controller_error(controller, r);
  2072. return JS::js_undefined();
  2073. }));
  2074. return {};
  2075. }
  2076. // https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller-from-underlying-source
  2077. WebIDL::ExceptionOr<void> set_up_readable_stream_default_controller_from_underlying_source(ReadableStream& stream, JS::Value underlying_source_value, UnderlyingSource underlying_source, double high_water_mark, GC::Ref<SizeAlgorithm> size_algorithm)
  2078. {
  2079. auto& realm = stream.realm();
  2080. // 1. Let controller be a new ReadableStreamDefaultController.
  2081. auto controller = realm.create<ReadableStreamDefaultController>(realm);
  2082. // 2. Let startAlgorithm be an algorithm that returns undefined.
  2083. auto start_algorithm = GC::create_function(realm.heap(), []() -> WebIDL::ExceptionOr<JS::Value> {
  2084. return JS::js_undefined();
  2085. });
  2086. // 3. Let pullAlgorithm be an algorithm that returns a promise resolved with undefined.
  2087. auto pull_algorithm = GC::create_function(realm.heap(), [&realm]() {
  2088. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  2089. });
  2090. // 4. Let cancelAlgorithm be an algorithm that returns a promise resolved with undefined.
  2091. auto cancel_algorithm = GC::create_function(realm.heap(), [&realm](JS::Value) {
  2092. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  2093. });
  2094. // 5. If underlyingSourceDict["start"] exists, then set startAlgorithm to an algorithm which returns the result of invoking underlyingSourceDict["start"] with argument list « controller » and callback this value underlyingSource.
  2095. if (underlying_source.start) {
  2096. start_algorithm = GC::create_function(realm.heap(), [controller, underlying_source_value, callback = underlying_source.start]() -> WebIDL::ExceptionOr<JS::Value> {
  2097. // Note: callback does not return a promise, so invoke_callback may return an abrupt completion
  2098. return TRY(WebIDL::invoke_callback(*callback, underlying_source_value, controller)).release_value();
  2099. });
  2100. }
  2101. // 6. If underlyingSourceDict["pull"] exists, then set pullAlgorithm to an algorithm which returns the result of invoking underlyingSourceDict["pull"] with argument list « controller » and callback this value underlyingSource.
  2102. if (underlying_source.pull) {
  2103. pull_algorithm = GC::create_function(realm.heap(), [&realm, controller, underlying_source_value, callback = underlying_source.pull]() {
  2104. // Note: callback returns a promise, so invoke_callback will never return an abrupt completion
  2105. auto result = MUST(WebIDL::invoke_callback(*callback, underlying_source_value, controller)).release_value();
  2106. return WebIDL::create_resolved_promise(realm, result);
  2107. });
  2108. }
  2109. // 7. If underlyingSourceDict["cancel"] exists, then set cancelAlgorithm to an algorithm which takes an argument reason and returns the result of invoking underlyingSourceDict["cancel"] with argument list « reason » and callback this value underlyingSource.
  2110. if (underlying_source.cancel) {
  2111. cancel_algorithm = GC::create_function(realm.heap(), [&realm, underlying_source_value, callback = underlying_source.cancel](JS::Value reason) {
  2112. // Note: callback returns a promise, so invoke_callback will never return an abrupt completion
  2113. auto result = MUST(WebIDL::invoke_callback(*callback, underlying_source_value, reason)).release_value();
  2114. return WebIDL::create_resolved_promise(realm, result);
  2115. });
  2116. }
  2117. // 8. Perform ? SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm).
  2118. return set_up_readable_stream_default_controller(stream, controller, start_algorithm, pull_algorithm, cancel_algorithm, high_water_mark, size_algorithm);
  2119. }
  2120. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-call-pull-if-needed
  2121. void readable_byte_stream_controller_call_pull_if_needed(ReadableByteStreamController& controller)
  2122. {
  2123. // 1. Let shouldPull be ! ReadableByteStreamControllerShouldCallPull(controller).
  2124. auto should_pull = readable_byte_stream_controller_should_call_pull(controller);
  2125. // 2. If shouldPull is false, return.
  2126. if (!should_pull)
  2127. return;
  2128. // 3. If controller.[[pulling]] is true,
  2129. if (controller.pulling()) {
  2130. // 1. Set controller.[[pullAgain]] to true.
  2131. controller.set_pull_again(true);
  2132. // 2. Return.
  2133. return;
  2134. }
  2135. // 4. Assert: controller.[[pullAgain]] is false.
  2136. VERIFY(!controller.pull_again());
  2137. // 5. Set controller.[[pulling]] to true.
  2138. controller.set_pulling(true);
  2139. // 6. Let pullPromise be the result of performing controller.[[pullAlgorithm]].
  2140. auto pull_promise = controller.pull_algorithm()->function()();
  2141. // 7. Upon fulfillment of pullPromise,
  2142. WebIDL::upon_fulfillment(*pull_promise, GC::create_function(controller.heap(), [&controller](JS::Value) -> WebIDL::ExceptionOr<JS::Value> {
  2143. // 1. Set controller.[[pulling]] to false.
  2144. controller.set_pulling(false);
  2145. // 2. If controller.[[pullAgain]] is true,
  2146. if (controller.pull_again()) {
  2147. // 1. Set controller.[[pullAgain]] to false.
  2148. controller.set_pull_again(false);
  2149. // 2. Perform ! ReadableByteStreamControllerCallPullIfNeeded(controller).
  2150. readable_byte_stream_controller_call_pull_if_needed(controller);
  2151. }
  2152. return JS::js_undefined();
  2153. }));
  2154. // 8. Upon rejection of pullPromise with reason e,
  2155. WebIDL::upon_rejection(*pull_promise, GC::create_function(controller.heap(), [&controller](JS::Value error) -> WebIDL::ExceptionOr<JS::Value> {
  2156. // 1. Perform ! ReadableByteStreamControllerError(controller, e).
  2157. readable_byte_stream_controller_error(controller, error);
  2158. return JS::js_undefined();
  2159. }));
  2160. }
  2161. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-clear-algorithms
  2162. void readable_byte_stream_controller_clear_algorithms(ReadableByteStreamController& controller)
  2163. {
  2164. // 1. Set controller.[[pullAlgorithm]] to undefined.
  2165. controller.set_pull_algorithm({});
  2166. // 2. Set controller.[[cancelAlgorithm]] to undefined.
  2167. controller.set_cancel_algorithm({});
  2168. }
  2169. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-clear-pending-pull-intos
  2170. void readable_byte_stream_controller_clear_pending_pull_intos(ReadableByteStreamController& controller)
  2171. {
  2172. // 1. Perform ! ReadableByteStreamControllerInvalidateBYOBRequest(controller).
  2173. readable_byte_stream_controller_invalidate_byob_request(controller);
  2174. // 2. Set controller.[[pendingPullIntos]] to a new empty list.
  2175. controller.pending_pull_intos().clear();
  2176. }
  2177. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-close
  2178. WebIDL::ExceptionOr<void> readable_byte_stream_controller_close(ReadableByteStreamController& controller)
  2179. {
  2180. auto& realm = controller.realm();
  2181. // 1. Let stream be controller.[[stream]].
  2182. auto stream = controller.stream();
  2183. // 2. If controller.[[closeRequested]] is true or stream.[[state]] is not "readable", return.
  2184. if (controller.close_requested() || stream->state() != ReadableStream::State::Readable)
  2185. return {};
  2186. // 3. If controller.[[queueTotalSize]] > 0,
  2187. if (controller.queue_total_size() > 0.0) {
  2188. // 1. Set controller.[[closeRequested]] to true.
  2189. controller.set_close_requested(true);
  2190. // 2. Return.
  2191. return {};
  2192. }
  2193. // 4. If controller.[[pendingPullIntos]] is not empty,
  2194. if (!controller.pending_pull_intos().is_empty()) {
  2195. // 1. Let firstPendingPullInto be controller.[[pendingPullIntos]][0].
  2196. auto& first_pending_pull_into = controller.pending_pull_intos().first();
  2197. // 2. If the remainder after dividing firstPendingPullInto’s bytes filled by firstPendingPullInto’s element size is not 0,
  2198. if (first_pending_pull_into.bytes_filled % first_pending_pull_into.element_size != 0) {
  2199. // 1. Let e be a new TypeError exception.
  2200. auto error = JS::TypeError::create(realm, "Cannot close controller in the middle of processing a write request"sv);
  2201. // 2. Perform ! ReadableByteStreamControllerError(controller, e).
  2202. readable_byte_stream_controller_error(controller, error);
  2203. // 3. Throw e.
  2204. return JS::throw_completion(error);
  2205. }
  2206. }
  2207. // 5. Perform ! ReadableByteStreamControllerClearAlgorithms(controller).
  2208. readable_byte_stream_controller_clear_algorithms(controller);
  2209. // 6. Perform ! ReadableStreamClose(stream).
  2210. readable_stream_close(*stream);
  2211. return {};
  2212. }
  2213. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-error
  2214. void readable_byte_stream_controller_error(ReadableByteStreamController& controller, JS::Value error)
  2215. {
  2216. // 1. Let stream be controller.[[stream]].
  2217. auto stream = controller.stream();
  2218. // 2. If stream.[[state]] is not "readable", return.
  2219. if (stream->state() != ReadableStream::State::Readable)
  2220. return;
  2221. // 3. Perform ! ReadableByteStreamControllerClearPendingPullIntos(controller).
  2222. readable_byte_stream_controller_clear_pending_pull_intos(controller);
  2223. // 4. Perform ! ResetQueue(controller).
  2224. reset_queue(controller);
  2225. // 5. Perform ! ReadableByteStreamControllerClearAlgorithms(controller).
  2226. readable_byte_stream_controller_clear_algorithms(controller);
  2227. // 6. Perform ! ReadableStreamError(stream, e).
  2228. readable_stream_error(*stream, error);
  2229. }
  2230. // https://streams.spec.whatwg.org/#abstract-opdef-readablebytestreamcontrollerfillreadrequestfromqueue
  2231. void readable_byte_stream_controller_fill_read_request_from_queue(ReadableByteStreamController& controller, GC::Ref<ReadRequest> read_request)
  2232. {
  2233. auto& vm = controller.vm();
  2234. auto& realm = controller.realm();
  2235. // 1. Assert: controller.[[queueTotalSize]] > 0.
  2236. VERIFY(controller.queue_total_size() > 0.0);
  2237. // 2. Let entry be controller.[[queue]][0].
  2238. // 3. Remove entry from controller.[[queue]].
  2239. auto entry = controller.queue().take_first();
  2240. // 4. Set controller.[[queueTotalSize]] to controller.[[queueTotalSize]] − entry’s byte length.
  2241. controller.set_queue_total_size(controller.queue_total_size() - entry.byte_length);
  2242. // 5. Perform ! ReadableByteStreamControllerHandleQueueDrain(controller).
  2243. readable_byte_stream_controller_handle_queue_drain(controller);
  2244. // 6. Let view be ! Construct(%Uint8Array%, « entry’s buffer, entry’s byte offset, entry’s byte length »).
  2245. auto view = MUST(JS::construct(vm, *realm.intrinsics().uint8_array_constructor(), entry.buffer, JS::Value(entry.byte_offset), JS::Value(entry.byte_length)));
  2246. // 7. Perform readRequest’s chunk steps, given view.
  2247. read_request->on_chunk(view);
  2248. }
  2249. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-get-desired-size
  2250. Optional<double> readable_byte_stream_controller_get_desired_size(ReadableByteStreamController const& controller)
  2251. {
  2252. auto stream = controller.stream();
  2253. // 1. Let state be controller.[[stream]].[[state]].
  2254. // 2. If state is "errored", return null.
  2255. if (stream->is_errored())
  2256. return {};
  2257. // 3. If state is "closed", return 0.
  2258. if (stream->is_closed())
  2259. return 0.0;
  2260. // 4. Return controller.[[strategyHWM]] − controller.[[queueTotalSize]].
  2261. return controller.strategy_hwm() - controller.queue_total_size();
  2262. }
  2263. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-handle-queue-drain
  2264. void readable_byte_stream_controller_handle_queue_drain(ReadableByteStreamController& controller)
  2265. {
  2266. // 1. Assert: controller.[[stream]].[[state]] is "readable".
  2267. VERIFY(controller.stream()->state() == ReadableStream::State::Readable);
  2268. // 2. If controller.[[queueTotalSize]] is 0 and controller.[[closeRequested]] is true,
  2269. if (controller.queue_total_size() == 0.0 && controller.close_requested()) {
  2270. // 1. Perform ! ReadableByteStreamControllerClearAlgorithms(controller).
  2271. readable_byte_stream_controller_clear_algorithms(controller);
  2272. // 2. Perform ! ReadableStreamClose(controller.[[stream]]).
  2273. readable_stream_close(*controller.stream());
  2274. }
  2275. // 3. Otherwise,
  2276. else {
  2277. // 1. Perform ! ReadableByteStreamControllerCallPullIfNeeded(controller).
  2278. readable_byte_stream_controller_call_pull_if_needed(controller);
  2279. }
  2280. }
  2281. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-invalidate-byob-request
  2282. void readable_byte_stream_controller_invalidate_byob_request(ReadableByteStreamController& controller)
  2283. {
  2284. // 1. If controller.[[byobRequest]] is null, return.
  2285. if (!controller.byob_request())
  2286. return;
  2287. // 2. Set controller.[[byobRequest]].[[controller]] to undefined.
  2288. controller.byob_request()->set_controller({});
  2289. // 3. Set controller.[[byobRequest]].[[view]] to null.
  2290. controller.byob_request()->set_view({});
  2291. // 4. Set controller.[[byobRequest]] to null.
  2292. controller.set_byob_request({});
  2293. }
  2294. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-error
  2295. bool readable_byte_stream_controller_should_call_pull(ReadableByteStreamController const& controller)
  2296. {
  2297. // 1. Let stream be controller.[[stream]].
  2298. auto stream = controller.stream();
  2299. // 2. If stream.[[state]] is not "readable", return false.
  2300. if (stream->state() != ReadableStream::State::Readable)
  2301. return false;
  2302. // 3. If controller.[[closeRequested]] is true, return false.
  2303. if (controller.close_requested())
  2304. return false;
  2305. // 4. If controller.[[started]] is false, return false.
  2306. if (!controller.started())
  2307. return false;
  2308. // 5. If ! ReadableStreamHasDefaultReader(stream) is true and ! ReadableStreamGetNumReadRequests(stream) > 0, return true.
  2309. if (readable_stream_has_default_reader(*stream) && readable_stream_get_num_read_requests(*stream) > 0)
  2310. return true;
  2311. // 6. If ! ReadableStreamHasBYOBReader(stream) is true and ! ReadableStreamGetNumReadIntoRequests(stream) > 0, return true.
  2312. if (readable_stream_has_byob_reader(*stream) && readable_stream_get_num_read_into_requests(*stream) > 0)
  2313. return true;
  2314. // 7. Let desiredSize be ! ReadableByteStreamControllerGetDesiredSize(controller).
  2315. auto desired_size = readable_byte_stream_controller_get_desired_size(controller);
  2316. // 8. Assert: desiredSize is not null.
  2317. VERIFY(desired_size.has_value());
  2318. // 9. If desiredSize > 0, return true.
  2319. if (*desired_size > 0.0)
  2320. return true;
  2321. // 10. Return false.
  2322. return false;
  2323. }
  2324. // https://streams.spec.whatwg.org/#create-readable-stream
  2325. WebIDL::ExceptionOr<GC::Ref<ReadableStream>> create_readable_stream(JS::Realm& realm, GC::Ref<StartAlgorithm> start_algorithm, GC::Ref<PullAlgorithm> pull_algorithm, GC::Ref<CancelAlgorithm> cancel_algorithm, Optional<double> high_water_mark, GC::Ptr<SizeAlgorithm> size_algorithm)
  2326. {
  2327. // 1. If highWaterMark was not passed, set it to 1.
  2328. if (!high_water_mark.has_value())
  2329. high_water_mark = 1.0;
  2330. // 2. If sizeAlgorithm was not passed, set it to an algorithm that returns 1.
  2331. if (!size_algorithm)
  2332. size_algorithm = GC::create_function(realm.heap(), [](JS::Value) { return JS::normal_completion(JS::Value(1)); });
  2333. // 3. Assert: ! IsNonNegativeNumber(highWaterMark) is true.
  2334. VERIFY(is_non_negative_number(JS::Value { *high_water_mark }));
  2335. // 4. Let stream be a new ReadableStream.
  2336. auto stream = realm.create<ReadableStream>(realm);
  2337. // 5. Perform ! InitializeReadableStream(stream).
  2338. initialize_readable_stream(*stream);
  2339. // 6. Let controller be a new ReadableStreamDefaultController.
  2340. auto controller = realm.create<ReadableStreamDefaultController>(realm);
  2341. // 7. Perform ? SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm).
  2342. TRY(set_up_readable_stream_default_controller(*stream, *controller, start_algorithm, pull_algorithm, cancel_algorithm, *high_water_mark, *size_algorithm));
  2343. // 8. Return stream.
  2344. return stream;
  2345. }
  2346. // https://streams.spec.whatwg.org/#abstract-opdef-createreadablebytestream
  2347. WebIDL::ExceptionOr<GC::Ref<ReadableStream>> create_readable_byte_stream(JS::Realm& realm, GC::Ref<StartAlgorithm> start_algorithm, GC::Ref<PullAlgorithm> pull_algorithm, GC::Ref<CancelAlgorithm> cancel_algorithm)
  2348. {
  2349. // 1. Let stream be a new ReadableStream.
  2350. auto stream = realm.create<ReadableStream>(realm);
  2351. // 2. Perform ! InitializeReadableStream(stream).
  2352. initialize_readable_stream(*stream);
  2353. // 3. Let controller be a new ReadableByteStreamController.
  2354. auto controller = realm.create<ReadableByteStreamController>(realm);
  2355. // 4. Perform ? SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, 0, undefined).
  2356. TRY(set_up_readable_byte_stream_controller(stream, controller, start_algorithm, pull_algorithm, cancel_algorithm, 0, JS::js_undefined()));
  2357. // 5. Return stream.
  2358. return stream;
  2359. }
  2360. // https://streams.spec.whatwg.org/#create-writable-stream
  2361. WebIDL::ExceptionOr<GC::Ref<WritableStream>> create_writable_stream(JS::Realm& realm, GC::Ref<StartAlgorithm> start_algorithm, GC::Ref<WriteAlgorithm> write_algorithm, GC::Ref<CloseAlgorithm> close_algorithm, GC::Ref<AbortAlgorithm> abort_algorithm, double high_water_mark, GC::Ref<SizeAlgorithm> size_algorithm)
  2362. {
  2363. // 1. Assert: ! IsNonNegativeNumber(highWaterMark) is true.
  2364. VERIFY(is_non_negative_number(JS::Value { high_water_mark }));
  2365. // 2. Let stream be a new WritableStream.
  2366. auto stream = realm.create<WritableStream>(realm);
  2367. // 3. Perform ! InitializeWritableStream(stream).
  2368. initialize_writable_stream(*stream);
  2369. // 4. Let controller be a new WritableStreamDefaultController.
  2370. auto controller = realm.create<WritableStreamDefaultController>(realm);
  2371. // 5. Perform ? SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm).
  2372. TRY(set_up_writable_stream_default_controller(*stream, *controller, move(start_algorithm), move(write_algorithm), move(close_algorithm), move(abort_algorithm), high_water_mark, move(size_algorithm)));
  2373. // 6. Return stream.
  2374. return stream;
  2375. }
  2376. // https://streams.spec.whatwg.org/#initialize-readable-stream
  2377. void initialize_readable_stream(ReadableStream& stream)
  2378. {
  2379. // 1. Set stream.[[state]] to "readable".
  2380. stream.set_state(ReadableStream::State::Readable);
  2381. // 2. Set stream.[[reader]] and stream.[[storedError]] to undefined.
  2382. stream.set_reader({});
  2383. stream.set_stored_error({});
  2384. // 3. Set stream.[[disturbed]] to false.
  2385. stream.set_disturbed(false);
  2386. }
  2387. // https://streams.spec.whatwg.org/#initialize-writable-stream
  2388. void initialize_writable_stream(WritableStream& stream)
  2389. {
  2390. // 1. Set stream.[[state]] to "writable".
  2391. stream.set_state(WritableStream::State::Writable);
  2392. // 2. Set stream.[[storedError]], stream.[[writer]], stream.[[controller]], stream.[[inFlightWriteRequest]],
  2393. // stream.[[closeRequest]], stream.[[inFlightCloseRequest]], and stream.[[pendingAbortRequest]] to undefined.
  2394. stream.set_stored_error(JS::js_undefined());
  2395. stream.set_writer({});
  2396. stream.set_controller({});
  2397. stream.set_in_flight_write_request({});
  2398. stream.set_close_request({});
  2399. stream.set_in_flight_close_request({});
  2400. stream.set_pending_abort_request({});
  2401. // 3. Set stream.[[writeRequests]] to a new empty list.
  2402. stream.write_requests().clear();
  2403. // 4. Set stream.[[backpressure]] to false.
  2404. stream.set_backpressure(false);
  2405. }
  2406. // https://streams.spec.whatwg.org/#acquire-writable-stream-default-writer
  2407. WebIDL::ExceptionOr<GC::Ref<WritableStreamDefaultWriter>> acquire_writable_stream_default_writer(WritableStream& stream)
  2408. {
  2409. auto& realm = stream.realm();
  2410. // 1. Let writer be a new WritableStreamDefaultWriter.
  2411. auto writer = realm.create<WritableStreamDefaultWriter>(realm);
  2412. // 2. Perform ? SetUpWritableStreamDefaultWriter(writer, stream).
  2413. TRY(set_up_writable_stream_default_writer(*writer, stream));
  2414. // 3. Return writer.
  2415. return writer;
  2416. }
  2417. // https://streams.spec.whatwg.org/#is-writable-stream-locked
  2418. bool is_writable_stream_locked(WritableStream const& stream)
  2419. {
  2420. // 1. If stream.[[writer]] is undefined, return false.
  2421. if (!stream.writer())
  2422. return false;
  2423. // 2. Return true.
  2424. return true;
  2425. }
  2426. // https://streams.spec.whatwg.org/#set-up-writable-stream-default-writer
  2427. WebIDL::ExceptionOr<void> set_up_writable_stream_default_writer(WritableStreamDefaultWriter& writer, WritableStream& stream)
  2428. {
  2429. auto& realm = writer.realm();
  2430. // 1. If ! IsWritableStreamLocked(stream) is true, throw a TypeError exception.
  2431. if (is_writable_stream_locked(stream))
  2432. return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Stream is locked"sv };
  2433. // 2. Set writer.[[stream]] to stream.
  2434. writer.set_stream(stream);
  2435. // 3. Set stream.[[writer]] to writer.
  2436. stream.set_writer(writer);
  2437. // 4. Let state be stream.[[state]].
  2438. auto state = stream.state();
  2439. // 5. If state is "writable",
  2440. if (state == WritableStream::State::Writable) {
  2441. // 1. If ! WritableStreamCloseQueuedOrInFlight(stream) is false and stream.[[backpressure]] is true, set writer.[[readyPromise]] to a new promise.
  2442. if (!writable_stream_close_queued_or_in_flight(stream) && stream.backpressure()) {
  2443. writer.set_ready_promise(WebIDL::create_promise(realm));
  2444. }
  2445. // 2. Otherwise, set writer.[[readyPromise]] to a promise resolved with undefined.
  2446. else {
  2447. writer.set_ready_promise(WebIDL::create_resolved_promise(realm, JS::js_undefined()));
  2448. }
  2449. // 3. Set writer.[[closedPromise]] to a new promise.
  2450. writer.set_closed_promise(WebIDL::create_promise(realm));
  2451. }
  2452. // 6. Otherwise, if state is "erroring",
  2453. else if (state == WritableStream::State::Erroring) {
  2454. // 1. Set writer.[[readyPromise]] to a promise rejected with stream.[[storedError]].
  2455. writer.set_ready_promise(WebIDL::create_rejected_promise(realm, stream.stored_error()));
  2456. // 2. Set writer.[[readyPromise]].[[PromiseIsHandled]] to true.
  2457. WebIDL::mark_promise_as_handled(*writer.ready_promise());
  2458. // 3. Set writer.[[closedPromise]] to a new promise.
  2459. writer.set_closed_promise(WebIDL::create_promise(realm));
  2460. }
  2461. // 7. Otherwise, if state is "closed",
  2462. else if (state == WritableStream::State::Closed) {
  2463. // 1. Set writer.[[readyPromise]] to a promise resolved with undefined.
  2464. writer.set_ready_promise(WebIDL::create_resolved_promise(realm, JS::js_undefined()));
  2465. // 2. Set writer.[[closedPromise]] to a promise resolved with undefined.
  2466. writer.set_closed_promise(WebIDL::create_resolved_promise(realm, JS::js_undefined()));
  2467. }
  2468. // 8. Otherwise,
  2469. else {
  2470. // 1. Assert: state is "errored".
  2471. VERIFY(state == WritableStream::State::Errored);
  2472. // 2. Let storedError be stream.[[storedError]].
  2473. auto stored_error = stream.stored_error();
  2474. // 3. Set writer.[[readyPromise]] to a promise rejected with storedError.
  2475. writer.set_ready_promise(WebIDL::create_rejected_promise(realm, stored_error));
  2476. // 4. Set writer.[[readyPromise]].[[PromiseIsHandled]] to true.
  2477. WebIDL::mark_promise_as_handled(*writer.ready_promise());
  2478. // 5. Set writer.[[closedPromise]] to a promise rejected with storedError.
  2479. writer.set_closed_promise(WebIDL::create_rejected_promise(realm, stored_error));
  2480. // 6. Set writer.[[closedPromise]].[[PromiseIsHandled]] to true.
  2481. WebIDL::mark_promise_as_handled(*writer.closed_promise());
  2482. }
  2483. return {};
  2484. }
  2485. // https://streams.spec.whatwg.org/#set-up-readable-byte-stream-controller
  2486. WebIDL::ExceptionOr<void> set_up_readable_byte_stream_controller(ReadableStream& stream, ReadableByteStreamController& controller, GC::Ref<StartAlgorithm> start_algorithm, GC::Ref<PullAlgorithm> pull_algorithm, GC::Ref<CancelAlgorithm> cancel_algorithm, double high_water_mark, JS::Value auto_allocate_chunk_size)
  2487. {
  2488. auto& realm = stream.realm();
  2489. // 1. Assert: stream.[[controller]] is undefined.
  2490. VERIFY(!stream.controller().has_value());
  2491. // 2. If autoAllocateChunkSize is not undefined,
  2492. if (!auto_allocate_chunk_size.is_undefined()) {
  2493. // 1. Assert: ! IsInteger(autoAllocateChunkSize) is true.
  2494. VERIFY(auto_allocate_chunk_size.is_integral_number());
  2495. // 2. Assert: autoAllocateChunkSize is positive.
  2496. VERIFY(auto_allocate_chunk_size.as_double() > 0);
  2497. }
  2498. // 3. Set controller.[[stream]] to stream.
  2499. controller.set_stream(stream);
  2500. // 4. Set controller.[[pullAgain]] and controller.[[pulling]] to false.
  2501. controller.set_pull_again(false);
  2502. controller.set_pulling(false);
  2503. // 5. Set controller.[[byobRequest]] to null.
  2504. controller.set_byob_request({});
  2505. // 6. Perform ! ResetQueue(controller).
  2506. reset_queue(controller);
  2507. // 7. Set controller.[[closeRequested]] and controller.[[started]] to false.
  2508. controller.set_close_requested(false);
  2509. controller.set_started(false);
  2510. // 8. Set controller.[[strategyHWM]] to highWaterMark.
  2511. controller.set_strategy_hwm(high_water_mark);
  2512. // 9. Set controller.[[pullAlgorithm]] to pullAlgorithm.
  2513. controller.set_pull_algorithm(pull_algorithm);
  2514. // 10. Set controller.[[cancelAlgorithm]] to cancelAlgorithm.
  2515. controller.set_cancel_algorithm(cancel_algorithm);
  2516. // 11. Set controller.[[autoAllocateChunkSize]] to autoAllocateChunkSize.
  2517. if (auto_allocate_chunk_size.is_integral_number())
  2518. controller.set_auto_allocate_chunk_size(auto_allocate_chunk_size.as_double());
  2519. // 12. Set controller.[[pendingPullIntos]] to a new empty list.
  2520. controller.pending_pull_intos().clear();
  2521. // 13. Set stream.[[controller]] to controller.
  2522. stream.set_controller(ReadableStreamController { controller });
  2523. // 14. Let startResult be the result of performing startAlgorithm.
  2524. auto start_result = TRY(start_algorithm->function()());
  2525. // 15. Let startPromise be a promise resolved with startResult.
  2526. auto start_promise = WebIDL::create_resolved_promise(realm, start_result);
  2527. // 16. Upon fulfillment of startPromise,
  2528. WebIDL::upon_fulfillment(start_promise, GC::create_function(controller.heap(), [&controller](JS::Value) -> WebIDL::ExceptionOr<JS::Value> {
  2529. // 1. Set controller.[[started]] to true.
  2530. controller.set_started(true);
  2531. // 2. Assert: controller.[[pulling]] is false.
  2532. VERIFY(!controller.pulling());
  2533. // 3. Assert: controller.[[pullAgain]] is false.
  2534. VERIFY(!controller.pull_again());
  2535. // 4. Perform ! ReadableByteStreamControllerCallPullIfNeeded(controller).
  2536. readable_byte_stream_controller_call_pull_if_needed(controller);
  2537. return JS::js_undefined();
  2538. }));
  2539. // 17. Upon rejection of startPromise with reason r,
  2540. WebIDL::upon_rejection(start_promise, GC::create_function(controller.heap(), [&controller](JS::Value r) -> WebIDL::ExceptionOr<JS::Value> {
  2541. // 1. Perform ! ReadableByteStreamControllerError(controller, r).
  2542. readable_byte_stream_controller_error(controller, r);
  2543. return JS::js_undefined();
  2544. }));
  2545. return {};
  2546. }
  2547. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-enqueue
  2548. WebIDL::ExceptionOr<void> readable_byte_stream_controller_enqueue(ReadableByteStreamController& controller, JS::Value chunk)
  2549. {
  2550. auto& vm = controller.vm();
  2551. auto& realm = controller.realm();
  2552. // 1. Let stream be controller.[[stream]].
  2553. auto stream = controller.stream();
  2554. // 2. If controller.[[closeRequested]] is true or stream.[[state]] is not "readable", return.
  2555. if (controller.close_requested() || stream->state() != ReadableStream ::State::Readable)
  2556. return {};
  2557. // 3. Let buffer be chunk.[[ViewedArrayBuffer]].
  2558. auto* typed_array = TRY(JS::typed_array_from(vm, chunk));
  2559. auto* buffer = typed_array->viewed_array_buffer();
  2560. // 4. Let byteOffset be chunk.[[ByteOffset]].
  2561. auto byte_offset = typed_array->byte_offset();
  2562. // 6. If ! IsDetachedBuffer(buffer) is true, throw a TypeError exception.
  2563. // FIXME: The streams spec has not been updated for resizable ArrayBuffer objects. We must perform step 6 before
  2564. // invoking TypedArrayByteLength in step 5. We also must check if the array is out-of-bounds, rather than
  2565. // just detached.
  2566. auto typed_array_record = JS::make_typed_array_with_buffer_witness_record(*typed_array, JS::ArrayBuffer::Order::SeqCst);
  2567. if (JS::is_typed_array_out_of_bounds(typed_array_record))
  2568. return vm.throw_completion<JS::TypeError>(JS::ErrorType::BufferOutOfBounds, "TypedArray"sv);
  2569. // 5. Let byteLength be chunk.[[ByteLength]].
  2570. auto byte_length = JS::typed_array_byte_length(typed_array_record);
  2571. // 7. Let transferredBuffer be ? TransferArrayBuffer(buffer).
  2572. auto transferred_buffer = TRY(transfer_array_buffer(realm, *buffer));
  2573. // 8. If controller.[[pendingPullIntos]] is not empty,
  2574. if (!controller.pending_pull_intos().is_empty()) {
  2575. // 1. Let firstPendingPullInto be controller.[[pendingPullIntos]][0].
  2576. auto& first_pending_pull_into = controller.pending_pull_intos().first();
  2577. // 2. If ! IsDetachedBuffer(firstPendingPullInto’s buffer) is true, throw a TypeError exception.
  2578. if (first_pending_pull_into.buffer->is_detached()) {
  2579. auto error = JS::TypeError::create(realm, "Buffer is detached"sv);
  2580. return JS::throw_completion(error);
  2581. }
  2582. // 3. Perform ! ReadableByteStreamControllerInvalidateBYOBRequest(controller).
  2583. readable_byte_stream_controller_invalidate_byob_request(controller);
  2584. // 4. Set firstPendingPullInto’s buffer to ! TransferArrayBuffer(firstPendingPullInto’s buffer).
  2585. first_pending_pull_into.buffer = MUST(transfer_array_buffer(realm, first_pending_pull_into.buffer));
  2586. // 5. If firstPendingPullInto’s reader type is "none", perform ? ReadableByteStreamControllerEnqueueDetachedPullIntoToQueue(controller, firstPendingPullInto).
  2587. if (first_pending_pull_into.reader_type == ReaderType::None)
  2588. TRY(readable_byte_stream_controller_enqueue_detached_pull_into_queue(controller, first_pending_pull_into));
  2589. }
  2590. // 9. If ! ReadableStreamHasDefaultReader(stream) is true,
  2591. if (readable_stream_has_default_reader(*stream)) {
  2592. // 1. Perform ! ReadableByteStreamControllerProcessReadRequestsUsingQueue(controller).
  2593. readable_byte_stream_controller_process_read_requests_using_queue(controller);
  2594. // 2. If ! ReadableStreamGetNumReadRequests(stream) is 0,
  2595. if (readable_stream_get_num_read_requests(*stream) == 0) {
  2596. // 1. Assert: controller.[[pendingPullIntos]] is empty.
  2597. VERIFY(controller.pending_pull_intos().is_empty());
  2598. // 2. Perform ! ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength).
  2599. readable_byte_stream_controller_enqueue_chunk_to_queue(controller, transferred_buffer, byte_offset, byte_length);
  2600. }
  2601. // 3. Otherwise.
  2602. else {
  2603. // 1. Assert: controller.[[queue]] is empty.
  2604. VERIFY(controller.queue().is_empty());
  2605. // 2. If controller.[[pendingPullIntos]] is not empty,
  2606. if (!controller.pending_pull_intos().is_empty()) {
  2607. // 1. Assert: controller.[[pendingPullIntos]][0]'s reader type is "default".
  2608. VERIFY(controller.pending_pull_intos().first().reader_type == ReaderType::Default);
  2609. // 2. Perform ! ReadableByteStreamControllerShiftPendingPullInto(controller).
  2610. readable_byte_stream_controller_shift_pending_pull_into(controller);
  2611. }
  2612. // 3. Let transferredView be ! Construct(%Uint8Array%, « transferredBuffer, byteOffset, byteLength »).
  2613. auto transferred_view = MUST(JS::construct(vm, *realm.intrinsics().uint8_array_constructor(), transferred_buffer, JS::Value(byte_offset), JS::Value(byte_length)));
  2614. // 4. Perform ! ReadableStreamFulfillReadRequest(stream, transferredView, false).
  2615. readable_stream_fulfill_read_request(*stream, transferred_view, false);
  2616. }
  2617. }
  2618. // 10. Otherwise, if ! ReadableStreamHasBYOBReader(stream) is true,
  2619. else if (readable_stream_has_byob_reader(*stream)) {
  2620. // 1. Perform ! ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength).
  2621. readable_byte_stream_controller_enqueue_chunk_to_queue(controller, transferred_buffer, byte_offset, byte_length);
  2622. // 2. Let filledPullIntos be the result of performing ! ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller).
  2623. auto filled_pull_intos = readable_byte_stream_controller_process_pull_into_descriptors_using_queue(controller);
  2624. // 3. For each filledPullInto of filledPullIntos,
  2625. for (auto& filled_pull_into : filled_pull_intos) {
  2626. // 1. Perform ! ReadableByteStreamControllerCommitPullIntoDescriptor(controller.[[stream]], filledPullInto).
  2627. readable_byte_stream_controller_commit_pull_into_descriptor(*stream, filled_pull_into);
  2628. }
  2629. }
  2630. // 11. Otherwise,
  2631. else {
  2632. // 1. Assert: ! IsReadableStreamLocked(stream) is false.
  2633. VERIFY(!is_readable_stream_locked(*stream));
  2634. // 2. Perform ! ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength).
  2635. readable_byte_stream_controller_enqueue_chunk_to_queue(controller, transferred_buffer, byte_offset, byte_length);
  2636. }
  2637. // 12. Perform ! ReadableByteStreamControllerCallPullIfNeeded(controller).
  2638. readable_byte_stream_controller_call_pull_if_needed(controller);
  2639. return {};
  2640. }
  2641. // https://streams.spec.whatwg.org/#transfer-array-buffer
  2642. WebIDL::ExceptionOr<GC::Ref<JS::ArrayBuffer>> transfer_array_buffer(JS::Realm& realm, JS::ArrayBuffer& buffer)
  2643. {
  2644. auto& vm = realm.vm();
  2645. // 1. Assert: ! IsDetachedBuffer(O) is false.
  2646. VERIFY(!buffer.is_detached());
  2647. // 2. Let arrayBufferData be O.[[ArrayBufferData]].
  2648. // 3. Let arrayBufferByteLength be O.[[ArrayBufferByteLength]].
  2649. auto array_buffer = buffer.buffer();
  2650. // 4. Perform ? DetachArrayBuffer(O).
  2651. TRY(JS::detach_array_buffer(vm, buffer));
  2652. // 5. Return a new ArrayBuffer object, created in the current Realm, whose [[ArrayBufferData]] internal slot value is arrayBufferData and whose [[ArrayBufferByteLength]] internal slot value is arrayBufferByteLength.
  2653. return JS::ArrayBuffer::create(realm, move(array_buffer));
  2654. }
  2655. // https://streams.spec.whatwg.org/#abstract-opdef-readablebytestreamcontrollerenqueuedetachedpullintotoqueue
  2656. WebIDL::ExceptionOr<void> readable_byte_stream_controller_enqueue_detached_pull_into_queue(ReadableByteStreamController& controller, PullIntoDescriptor& pull_into_descriptor)
  2657. {
  2658. // 1. Assert: pullIntoDescriptor’s reader type is "none".
  2659. VERIFY(pull_into_descriptor.reader_type == ReaderType::None);
  2660. // 2. If pullIntoDescriptor’s bytes filled > 0, perform ? ReadableByteStreamControllerEnqueueClonedChunkToQueue(controller, pullIntoDescriptor’s buffer, pullIntoDescriptor’s byte offset, pullIntoDescriptor’s bytes filled).
  2661. if (pull_into_descriptor.bytes_filled > 0)
  2662. TRY(readable_byte_stream_controller_enqueue_cloned_chunk_to_queue(controller, pull_into_descriptor.buffer, pull_into_descriptor.byte_offset, pull_into_descriptor.bytes_filled));
  2663. // 3. Perform ! ReadableByteStreamControllerShiftPendingPullInto(controller).
  2664. readable_byte_stream_controller_shift_pending_pull_into(controller);
  2665. return {};
  2666. }
  2667. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-commit-pull-into-descriptor
  2668. void readable_byte_stream_controller_commit_pull_into_descriptor(ReadableStream& stream, PullIntoDescriptor const& pull_into_descriptor)
  2669. {
  2670. // 1. Assert: stream.[[state]] is not "errored".
  2671. VERIFY(!stream.is_errored());
  2672. // 2. Assert: pullIntoDescriptor.reader type is not "none".
  2673. VERIFY(pull_into_descriptor.reader_type != ReaderType::None);
  2674. // 3. Let done be false.
  2675. bool done = false;
  2676. // 4. If stream.[[state]] is "closed",
  2677. if (stream.is_closed()) {
  2678. // 1. Assert: the remainder after dividing pullIntoDescriptor’s bytes filled by pullIntoDescriptor’s element size is 0.
  2679. VERIFY(pull_into_descriptor.bytes_filled % pull_into_descriptor.element_size == 0);
  2680. // 2. Set done to true.
  2681. done = true;
  2682. }
  2683. // 5. Let filledView be ! ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor).
  2684. auto filled_view = readable_byte_stream_controller_convert_pull_into_descriptor(stream.realm(), pull_into_descriptor);
  2685. // 6. If pullIntoDescriptor’s reader type is "default",
  2686. if (pull_into_descriptor.reader_type == ReaderType::Default) {
  2687. // 1. Perform ! ReadableStreamFulfillReadRequest(stream, filledView, done).
  2688. readable_stream_fulfill_read_request(stream, filled_view, done);
  2689. }
  2690. // 7. Otherwise,
  2691. else {
  2692. // 1. Assert: pullIntoDescriptor’s reader type is "byob".
  2693. VERIFY(pull_into_descriptor.reader_type == ReaderType::Byob);
  2694. // 2. Perform ! ReadableStreamFulfillReadIntoRequest(stream, filledView, done).
  2695. readable_stream_fulfill_read_into_request(stream, filled_view, done);
  2696. }
  2697. }
  2698. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-process-pull-into-descriptors-using-queue
  2699. SinglyLinkedList<PullIntoDescriptor> readable_byte_stream_controller_process_pull_into_descriptors_using_queue(ReadableByteStreamController& controller)
  2700. {
  2701. // 1. Assert: controller.[[closeRequested]] is false.
  2702. VERIFY(!controller.close_requested());
  2703. // 2. Let filledPullIntos be a new empty list.
  2704. SinglyLinkedList<PullIntoDescriptor> filled_pull_intos;
  2705. // 3. While controller.[[pendingPullIntos]] is not empty,
  2706. while (!controller.pending_pull_intos().is_empty()) {
  2707. // 1. If controller.[[queueTotalSize]] is 0, then break.
  2708. if (controller.queue_total_size() == 0)
  2709. break;
  2710. // 2. Let pullIntoDescriptor be controller.[[pendingPullIntos]][0].
  2711. auto& pull_into_descriptor = controller.pending_pull_intos().first();
  2712. // 3. If ! ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) is true,
  2713. if (readable_byte_stream_controller_fill_pull_into_descriptor_from_queue(controller, pull_into_descriptor)) {
  2714. // NOTE: We store the returned pull into descriptor here as the 'shift pending pull into' will remove
  2715. // the first entry into the list which we have a reference to above.
  2716. // 1. Perform ! ReadableByteStreamControllerShiftPendingPullInto(controller).
  2717. auto descriptor = readable_byte_stream_controller_shift_pending_pull_into(controller);
  2718. // 2. Append pullIntoDescriptor to filledPullIntos.
  2719. filled_pull_intos.append(descriptor);
  2720. }
  2721. }
  2722. // 4. Return filledPullIntos.
  2723. return filled_pull_intos;
  2724. }
  2725. // https://streams.spec.whatwg.org/#abstract-opdef-readablebytestreamcontrollerprocessreadrequestsusingqueue
  2726. void readable_byte_stream_controller_process_read_requests_using_queue(ReadableByteStreamController& controller)
  2727. {
  2728. // 1. Let reader be controller.[[stream]].[[reader]].
  2729. auto reader = controller.stream()->reader();
  2730. // 2. Assert: reader implements ReadableStreamDefaultReader.
  2731. VERIFY(reader->has<GC::Ref<ReadableStreamDefaultReader>>());
  2732. // 3. While reader.[[readRequests]] is not empty,
  2733. auto readable_stream_default_reader = reader->get<GC::Ref<ReadableStreamDefaultReader>>();
  2734. while (!readable_stream_default_reader->read_requests().is_empty()) {
  2735. // 1. If controller.[[queueTotalSize]] is 0, return.
  2736. if (controller.queue_total_size() == 0.0)
  2737. return;
  2738. // 2. Let readRequest be reader.[[readRequests]][0].
  2739. // 3. Remove readRequest from reader.[[readRequests]].
  2740. auto read_request = readable_stream_default_reader->read_requests().take_first();
  2741. // 4. Perform ! ReadableByteStreamControllerFillReadRequestFromQueue(controller, readRequest).
  2742. readable_byte_stream_controller_fill_read_request_from_queue(controller, read_request);
  2743. }
  2744. }
  2745. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-enqueue-chunk-to-queue
  2746. void readable_byte_stream_controller_enqueue_chunk_to_queue(ReadableByteStreamController& controller, GC::Ref<JS::ArrayBuffer> buffer, u32 byte_offset, u32 byte_length)
  2747. {
  2748. // 1. Append a new readable byte stream queue entry with buffer buffer, byte offset byteOffset, and byte length byteLength to controller.[[queue]].
  2749. controller.queue().append(ReadableByteStreamQueueEntry {
  2750. .buffer = buffer,
  2751. .byte_offset = byte_offset,
  2752. .byte_length = byte_length,
  2753. });
  2754. // 2. Set controller.[[queueTotalSize]] to controller.[[queueTotalSize]] + byteLength.
  2755. controller.set_queue_total_size(controller.queue_total_size() + byte_length);
  2756. }
  2757. // https://streams.spec.whatwg.org/#abstract-opdef-readablebytestreamcontrollerenqueueclonedchunktoqueue
  2758. WebIDL::ExceptionOr<void> readable_byte_stream_controller_enqueue_cloned_chunk_to_queue(ReadableByteStreamController& controller, JS::ArrayBuffer& buffer, u64 byte_offset, u64 byte_length)
  2759. {
  2760. auto& vm = controller.vm();
  2761. // 1. Let cloneResult be CloneArrayBuffer(buffer, byteOffset, byteLength, %ArrayBuffer%).
  2762. auto clone_result = JS::clone_array_buffer(vm, buffer, byte_offset, byte_length);
  2763. // 2. If cloneResult is an abrupt completion,
  2764. if (clone_result.is_throw_completion()) {
  2765. auto throw_completion = Bindings::throw_dom_exception_if_needed(vm, [&] { return clone_result; }).throw_completion();
  2766. // 1. Perform ! ReadableByteStreamControllerError(controller, cloneResult.[[Value]]).
  2767. readable_byte_stream_controller_error(controller, throw_completion.value().value());
  2768. // 2. Return cloneResult.
  2769. // Note: We need to return the throw_completion object here, as enqueue needs to throw the same object that the controller is errored with
  2770. return throw_completion;
  2771. }
  2772. // 3. Perform ! ReadableByteStreamControllerEnqueueChunkToQueue(controller, cloneResult.[[Value]], 0, byteLength).
  2773. readable_byte_stream_controller_enqueue_chunk_to_queue(controller, *clone_result.release_value(), 0, byte_length);
  2774. return {};
  2775. }
  2776. // https://streams.spec.whatwg.org/#readable-byte-stream-controller-shift-pending-pull-into
  2777. PullIntoDescriptor readable_byte_stream_controller_shift_pending_pull_into(ReadableByteStreamController& controller)
  2778. {
  2779. // 1. Assert: controller.[[byobRequest]] is null.
  2780. VERIFY(!controller.raw_byob_request());
  2781. // 2. Let descriptor be controller.[[pendingPullIntos]][0].
  2782. // 3. Remove descriptor from controller.[[pendingPullIntos]].
  2783. auto descriptor = controller.pending_pull_intos().take_first();
  2784. // 4. Return descriptor.
  2785. return descriptor;
  2786. }
  2787. // https://streams.spec.whatwg.org/#writable-stream-abort
  2788. GC::Ref<WebIDL::Promise> writable_stream_abort(WritableStream& stream, JS::Value reason)
  2789. {
  2790. auto& realm = stream.realm();
  2791. // 1. If stream.[[state]] is "closed" or "errored", return a promise resolved with undefined.
  2792. auto state = stream.state();
  2793. if (state == WritableStream::State::Closed || state == WritableStream::State::Errored)
  2794. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  2795. // 2. Signal abort on stream.[[controller]].[[signal]] with reason.
  2796. stream.controller()->signal()->signal_abort(reason);
  2797. // 3. Let state be stream.[[state]].
  2798. state = stream.state();
  2799. // 4. If state is "closed" or "errored", return a promise resolved with undefined.
  2800. if (state == WritableStream::State::Closed || state == WritableStream::State::Errored)
  2801. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  2802. // 5. If stream.[[pendingAbortRequest]] is not undefined, return stream.[[pendingAbortRequest]]'s promise.
  2803. if (stream.pending_abort_request().has_value())
  2804. return stream.pending_abort_request()->promise;
  2805. // 6. Assert: state is "writable" or "erroring".
  2806. VERIFY(state == WritableStream::State::Writable || state == WritableStream::State::Erroring);
  2807. // 7. Let wasAlreadyErroring be false.
  2808. auto was_already_erroring = false;
  2809. // 8. If state is "erroring",
  2810. if (state == WritableStream::State::Erroring) {
  2811. // 1. Set wasAlreadyErroring to true.
  2812. was_already_erroring = true;
  2813. // 2. Set reason to undefined.
  2814. reason = JS::js_undefined();
  2815. }
  2816. // 9. Let promise be a new promise.
  2817. auto promise = WebIDL::create_promise(realm);
  2818. // 10. Set stream.[[pendingAbortRequest]] to a new pending abort request whose promise is promise, reason is reason, and was already erroring is wasAlreadyErroring.
  2819. stream.set_pending_abort_request(PendingAbortRequest { promise, reason, was_already_erroring });
  2820. // 11. If wasAlreadyErroring is false, perform ! WritableStreamStartErroring(stream, reason).
  2821. if (!was_already_erroring)
  2822. writable_stream_start_erroring(stream, reason);
  2823. // 12. Return promise.
  2824. return promise;
  2825. }
  2826. // https://streams.spec.whatwg.org/#writable-stream-close
  2827. GC::Ref<WebIDL::Promise> writable_stream_close(WritableStream& stream)
  2828. {
  2829. auto& realm = stream.realm();
  2830. // 1. Let state be stream.[[state]].
  2831. auto state = stream.state();
  2832. // 2. If state is "closed" or "errored", return a promise rejected with a TypeError exception.
  2833. if (state == WritableStream::State::Closed || state == WritableStream::State::Errored) {
  2834. auto message = state == WritableStream::State::Closed ? "Cannot close a closed stream"sv : "Cannot close an errored stream"sv;
  2835. auto exception = JS::TypeError::create(realm, message);
  2836. return WebIDL::create_rejected_promise(realm, exception);
  2837. }
  2838. // 3. Assert: state is "writable" or "erroring".
  2839. VERIFY(state == WritableStream::State::Writable || state == WritableStream::State::Erroring);
  2840. // 4. Assert: ! WritableStreamCloseQueuedOrInFlight(stream) is false.
  2841. VERIFY(!writable_stream_close_queued_or_in_flight(stream));
  2842. // 5. Let promise be a new promise.
  2843. auto promise = WebIDL::create_promise(realm);
  2844. // 6. Set stream.[[closeRequest]] to promise.
  2845. stream.set_close_request(promise);
  2846. // 7. Let writer be stream.[[writer]].
  2847. auto writer = stream.writer();
  2848. // 8. If writer is not undefined, and stream.[[backpressure]] is true, and state is "writable", resolve writer.[[readyPromise]] with undefined.
  2849. if (writer && stream.backpressure() && state == WritableStream::State::Writable)
  2850. WebIDL::resolve_promise(realm, *writer->ready_promise(), JS::js_undefined());
  2851. // 9. Perform ! WritableStreamDefaultControllerClose(stream.[[controller]]).
  2852. writable_stream_default_controller_close(*stream.controller());
  2853. // 10. Return promise.
  2854. return promise;
  2855. }
  2856. // https://streams.spec.whatwg.org/#writable-stream-add-write-request
  2857. GC::Ref<WebIDL::Promise> writable_stream_add_write_request(WritableStream& stream)
  2858. {
  2859. auto& realm = stream.realm();
  2860. // 1. Assert: ! IsWritableStreamLocked(stream) is true.
  2861. VERIFY(is_writable_stream_locked(stream));
  2862. // 2. Assert: stream.[[state]] is "writable".
  2863. VERIFY(stream.state() == WritableStream::State::Writable);
  2864. // 3. Let promise be a new promise.
  2865. auto promise = WebIDL::create_promise(realm);
  2866. // 4. Append promise to stream.[[writeRequests]].
  2867. stream.write_requests().append(promise);
  2868. // 5. Return promise.
  2869. return promise;
  2870. }
  2871. // https://streams.spec.whatwg.org/#writable-stream-close-queued-or-in-flight
  2872. bool writable_stream_close_queued_or_in_flight(WritableStream const& stream)
  2873. {
  2874. // 1. If stream.[[closeRequest]] is undefined and stream.[[inFlightCloseRequest]] is undefined, return false.
  2875. if (!stream.close_request() && !stream.in_flight_close_request())
  2876. return false;
  2877. // 2. Return true.
  2878. return true;
  2879. }
  2880. // https://streams.spec.whatwg.org/#writable-stream-deal-with-rejection
  2881. void writable_stream_deal_with_rejection(WritableStream& stream, JS::Value error)
  2882. {
  2883. // 1. Let state be stream.[[state]].
  2884. auto state = stream.state();
  2885. // 2. If state is "writable",
  2886. if (state == WritableStream::State::Writable) {
  2887. // 1. Perform ! WritableStreamStartErroring(stream, error).
  2888. writable_stream_start_erroring(stream, error);
  2889. // 2. Return.
  2890. return;
  2891. }
  2892. // 3. Assert: state is "erroring".
  2893. VERIFY(state == WritableStream::State::Erroring);
  2894. // 4. Perform ! WritableStreamFinishErroring(stream).
  2895. writable_stream_finish_erroring(stream);
  2896. }
  2897. // https://streams.spec.whatwg.org/#writable-stream-finish-erroring
  2898. void writable_stream_finish_erroring(WritableStream& stream)
  2899. {
  2900. auto& realm = stream.realm();
  2901. // 1. Assert: stream.[[state]] is "erroring".
  2902. VERIFY(stream.state() == WritableStream::State::Erroring);
  2903. // 2. Assert: ! WritableStreamHasOperationMarkedInFlight(stream) is false.
  2904. VERIFY(!writable_stream_has_operation_marked_in_flight(stream));
  2905. // 3. Set stream.[[state]] to "errored".
  2906. stream.set_state(WritableStream::State::Errored);
  2907. // 4. Perform ! stream.[[controller]].[[ErrorSteps]]().
  2908. stream.controller()->error_steps();
  2909. // 5. Let storedError be stream.[[storedError]].
  2910. auto stored_error = stream.stored_error();
  2911. // 6. For each writeRequest of stream.[[writeRequests]]:
  2912. for (auto& write_request : stream.write_requests()) {
  2913. // 1. Reject writeRequest with storedError.
  2914. WebIDL::reject_promise(realm, *write_request, stored_error);
  2915. }
  2916. // 7. Set stream.[[writeRequests]] to an empty list.
  2917. stream.write_requests().clear();
  2918. // 8. If stream.[[pendingAbortRequest]] is undefined,
  2919. if (!stream.pending_abort_request().has_value()) {
  2920. // 1. Perform ! WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream).
  2921. writable_stream_reject_close_and_closed_promise_if_needed(stream);
  2922. // 2. Return.
  2923. return;
  2924. }
  2925. // 9. Let abortRequest be stream.[[pendingAbortRequest]].
  2926. // 10. Set stream.[[pendingAbortRequest]] to undefined.
  2927. auto abort_request = stream.pending_abort_request().release_value();
  2928. // 11. If abortRequest’s was already erroring is true,
  2929. if (abort_request.was_already_erroring) {
  2930. // 1. Reject abortRequest’s promise with storedError.
  2931. WebIDL::reject_promise(realm, abort_request.promise, stored_error);
  2932. // 2. Perform ! WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream).
  2933. writable_stream_reject_close_and_closed_promise_if_needed(stream);
  2934. // 3. Return.
  2935. return;
  2936. }
  2937. // 12. Let promise be ! stream.[[controller]].[[AbortSteps]](abortRequest’s reason).
  2938. auto promise = stream.controller()->abort_steps(abort_request.reason);
  2939. // 13. Upon fulfillment of promise,
  2940. WebIDL::upon_fulfillment(*promise, GC::create_function(realm.heap(), [&realm, &stream, abort_promise = abort_request.promise](JS::Value) -> WebIDL::ExceptionOr<JS::Value> {
  2941. // 1. Resolve abortRequest’s promise with undefined.
  2942. WebIDL::resolve_promise(realm, abort_promise, JS::js_undefined());
  2943. // 2. Perform ! WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream).
  2944. writable_stream_reject_close_and_closed_promise_if_needed(stream);
  2945. return JS::js_undefined();
  2946. }));
  2947. // 14. Upon rejection of promise with reason reason,
  2948. WebIDL::upon_rejection(*promise, GC::create_function(realm.heap(), [&realm, &stream, abort_promise = abort_request.promise](JS::Value reason) -> WebIDL::ExceptionOr<JS::Value> {
  2949. // 1. Reject abortRequest’s promise with reason.
  2950. WebIDL::reject_promise(realm, abort_promise, reason);
  2951. // 2. Perform ! WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream).
  2952. writable_stream_reject_close_and_closed_promise_if_needed(stream);
  2953. return JS::js_undefined();
  2954. }));
  2955. }
  2956. // https://streams.spec.whatwg.org/#writable-stream-finish-in-flight-close
  2957. void writable_stream_finish_in_flight_close(WritableStream& stream)
  2958. {
  2959. auto& realm = stream.realm();
  2960. // 1. Assert: stream.[[inFlightCloseRequest]] is not undefined.
  2961. VERIFY(stream.in_flight_close_request());
  2962. // 2. Resolve stream.[[inFlightCloseRequest]] with undefined.
  2963. WebIDL::resolve_promise(realm, *stream.in_flight_close_request(), JS::js_undefined());
  2964. // 3. Set stream.[[inFlightCloseRequest]] to undefined.
  2965. stream.set_in_flight_close_request({});
  2966. // 4. Let state be stream.[[state]].
  2967. auto state = stream.state();
  2968. // 5. Assert: stream.[[state]] is "writable" or "erroring".
  2969. VERIFY(state == WritableStream::State::Writable || state == WritableStream::State::Erroring);
  2970. // 6. If state is "erroring",
  2971. if (state == WritableStream::State::Erroring) {
  2972. // 1. Set stream.[[storedError]] to undefined.
  2973. stream.set_stored_error(JS::js_undefined());
  2974. // 2. If stream.[[pendingAbortRequest]] is not undefined,
  2975. if (stream.pending_abort_request().has_value()) {
  2976. // 1. Resolve stream.[[pendingAbortRequest]]'s promise with undefined.
  2977. // 2. Set stream.[[pendingAbortRequest]] to undefined.
  2978. WebIDL::resolve_promise(realm, stream.pending_abort_request().release_value().promise, JS::js_undefined());
  2979. }
  2980. }
  2981. // 7. Set stream.[[state]] to "closed".
  2982. stream.set_state(WritableStream::State::Closed);
  2983. // 8. Let writer be stream.[[writer]].
  2984. auto writer = stream.writer();
  2985. // 9. If writer is not undefined, resolve writer.[[closedPromise]] with undefined.
  2986. if (writer)
  2987. WebIDL::resolve_promise(realm, *writer->closed_promise(), JS::js_undefined());
  2988. // 10. Assert: stream.[[pendingAbortRequest]] is undefined.
  2989. VERIFY(!stream.pending_abort_request().has_value());
  2990. // 11. Assert: stream.[[storedError]] is undefined.
  2991. VERIFY(stream.stored_error().is_undefined());
  2992. }
  2993. // https://streams.spec.whatwg.org/#writable-stream-finish-in-flight-close-with-error
  2994. void writable_stream_finish_in_flight_close_with_error(WritableStream& stream, JS::Value error)
  2995. {
  2996. auto& realm = stream.realm();
  2997. // 1. Assert: stream.[[inFlightCloseRequest]] is not undefined.
  2998. VERIFY(stream.in_flight_close_request());
  2999. // 2. Reject stream.[[inFlightCloseRequest]] with error.
  3000. WebIDL::reject_promise(realm, *stream.in_flight_close_request(), error);
  3001. // 3. Set stream.[[inFlightCloseRequest]] to undefined.
  3002. stream.set_in_flight_close_request({});
  3003. // 4. Assert: stream.[[state]] is "writable" or "erroring".
  3004. auto state = stream.state();
  3005. VERIFY(state == WritableStream::State::Writable || state == WritableStream::State::Erroring);
  3006. // 5. If stream.[[pendingAbortRequest]] is not undefined,
  3007. if (stream.pending_abort_request().has_value()) {
  3008. // 1. Reject stream.[[pendingAbortRequest]]'s promise with error.
  3009. // 2. Set stream.[[pendingAbortRequest]] to undefined.
  3010. WebIDL::reject_promise(realm, stream.pending_abort_request().release_value().promise, error);
  3011. }
  3012. // 6. Perform ! WritableStreamDealWithRejection(stream, error).
  3013. writable_stream_deal_with_rejection(stream, error);
  3014. }
  3015. // https://streams.spec.whatwg.org/#writable-stream-finish-in-flight-write
  3016. void writable_stream_finish_in_flight_write(WritableStream& stream)
  3017. {
  3018. auto& realm = stream.realm();
  3019. // 1. Assert: stream.[[inFlightWriteRequest]] is not undefined.
  3020. VERIFY(stream.in_flight_write_request());
  3021. // 2. Resolve stream.[[inFlightWriteRequest]] with undefined.
  3022. WebIDL::resolve_promise(realm, *stream.in_flight_write_request(), JS::js_undefined());
  3023. // 3. Set stream.[[inFlightWriteRequest]] to undefined.
  3024. stream.set_in_flight_write_request({});
  3025. }
  3026. // https://streams.spec.whatwg.org/#writable-stream-finish-in-flight-write-with-error
  3027. void writable_stream_finish_in_flight_write_with_error(WritableStream& stream, JS::Value error)
  3028. {
  3029. auto& realm = stream.realm();
  3030. // 1. Assert: stream.[[inFlightWriteRequest]] is not undefined.
  3031. VERIFY(stream.in_flight_write_request());
  3032. // 2. Reject stream.[[inFlightWriteRequest]] with error.
  3033. WebIDL::reject_promise(realm, *stream.in_flight_write_request(), error);
  3034. // 3. Set stream.[[inFlightWriteRequest]] to undefined.
  3035. stream.set_in_flight_write_request({});
  3036. // 4. Assert: stream.[[state]] is "writable" or "erroring".
  3037. auto state = stream.state();
  3038. VERIFY(state == WritableStream::State::Writable || state == WritableStream::State::Erroring);
  3039. // 5. Perform ! WritableStreamDealWithRejection(stream, error).
  3040. writable_stream_deal_with_rejection(stream, error);
  3041. }
  3042. // https://streams.spec.whatwg.org/#writable-stream-has-operation-marked-in-flight
  3043. bool writable_stream_has_operation_marked_in_flight(WritableStream const& stream)
  3044. {
  3045. // 1. If stream.[[inFlightWriteRequest]] is undefined and stream.[[inFlightCloseRequest]] is undefined, return false.
  3046. if (!stream.in_flight_write_request() && !stream.in_flight_close_request())
  3047. return false;
  3048. // 2. Return true.
  3049. return true;
  3050. }
  3051. // https://streams.spec.whatwg.org/#writable-stream-mark-close-request-in-flight
  3052. void writable_stream_mark_close_request_in_flight(WritableStream& stream)
  3053. {
  3054. // 1. Assert: stream.[[inFlightCloseRequest]] is undefined.
  3055. VERIFY(!stream.in_flight_close_request());
  3056. // 2. Assert: stream.[[closeRequest]] is not undefined.
  3057. VERIFY(stream.close_request());
  3058. // 3. Set stream.[[inFlightCloseRequest]] to stream.[[closeRequest]].
  3059. stream.set_in_flight_close_request(stream.close_request());
  3060. // 4. Set stream.[[closeRequest]] to undefined.
  3061. stream.set_close_request({});
  3062. }
  3063. // https://streams.spec.whatwg.org/#writable-stream-mark-first-write-request-in-flight
  3064. void writable_stream_mark_first_write_request_in_flight(WritableStream& stream)
  3065. {
  3066. // 1. Assert: stream.[[inFlightWriteRequest]] is undefined.
  3067. VERIFY(!stream.in_flight_write_request());
  3068. // 2. Assert: stream.[[writeRequests]] is not empty.
  3069. VERIFY(!stream.write_requests().is_empty());
  3070. // 3. Let writeRequest be stream.[[writeRequests]][0].
  3071. // 4. Remove writeRequest from stream.[[writeRequests]].
  3072. auto write_request = stream.write_requests().take_first();
  3073. // 5. Set stream.[[inFlightWriteRequest]] to writeRequest.
  3074. stream.set_in_flight_write_request(write_request);
  3075. }
  3076. // https://streams.spec.whatwg.org/#writable-stream-reject-close-and-closed-promise-if-needed
  3077. void writable_stream_reject_close_and_closed_promise_if_needed(WritableStream& stream)
  3078. {
  3079. auto& realm = stream.realm();
  3080. // 1. Assert: stream.[[state]] is "errored".
  3081. VERIFY(stream.state() == WritableStream::State::Errored);
  3082. // 2. If stream.[[closeRequest]] is not undefined,
  3083. if (stream.close_request()) {
  3084. // 1. Assert: stream.[[inFlightCloseRequest]] is undefined.
  3085. VERIFY(!stream.in_flight_close_request());
  3086. // 2. Reject stream.[[closeRequest]] with stream.[[storedError]].
  3087. WebIDL::reject_promise(realm, *stream.close_request(), stream.stored_error());
  3088. // 3. Set stream.[[closeRequest]] to undefined.
  3089. stream.set_close_request({});
  3090. }
  3091. // 3. Let writer be stream.[[writer]].
  3092. auto writer = stream.writer();
  3093. // 4. If writer is not undefined,
  3094. if (writer) {
  3095. // 1. Reject writer.[[closedPromise]] with stream.[[storedError]].
  3096. WebIDL::reject_promise(realm, *writer->closed_promise(), stream.stored_error());
  3097. // 2. Set writer.[[closedPromise]].[[PromiseIsHandled]] to true.
  3098. WebIDL::mark_promise_as_handled(*writer->closed_promise());
  3099. }
  3100. }
  3101. // https://streams.spec.whatwg.org/#writable-stream-start-erroring
  3102. void writable_stream_start_erroring(WritableStream& stream, JS::Value reason)
  3103. {
  3104. // 1. Assert: stream.[[storedError]] is undefined.
  3105. VERIFY(stream.stored_error().is_undefined());
  3106. // 2. Assert: stream.[[state]] is "writable".
  3107. VERIFY(stream.state() == WritableStream::State::Writable);
  3108. // 3. Let controller be stream.[[controller]].
  3109. auto controller = stream.controller();
  3110. // 4. Assert: controller is not undefined.
  3111. VERIFY(controller);
  3112. // 5. Set stream.[[state]] to "erroring".
  3113. stream.set_state(WritableStream::State::Erroring);
  3114. // 6. Set stream.[[storedError]] to reason.
  3115. stream.set_stored_error(reason);
  3116. // 7. Let writer be stream.[[writer]].
  3117. auto writer = stream.writer();
  3118. // 8. If writer is not undefined, perform ! WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason).
  3119. if (writer)
  3120. writable_stream_default_writer_ensure_ready_promise_rejected(*writer, reason);
  3121. // 9. If ! WritableStreamHasOperationMarkedInFlight(stream) is false and controller.[[started]] is true, perform ! WritableStreamFinishErroring(stream).
  3122. if (!writable_stream_has_operation_marked_in_flight(stream) && controller->started())
  3123. writable_stream_finish_erroring(stream);
  3124. }
  3125. // https://streams.spec.whatwg.org/#writable-stream-update-backpressure
  3126. void writable_stream_update_backpressure(WritableStream& stream, bool backpressure)
  3127. {
  3128. auto& realm = stream.realm();
  3129. // 1. Assert: stream.[[state]] is "writable".
  3130. VERIFY(stream.state() == WritableStream::State::Writable);
  3131. // 2. Assert: ! WritableStreamCloseQueuedOrInFlight(stream) is false.
  3132. VERIFY(!writable_stream_close_queued_or_in_flight(stream));
  3133. // 3. Let writer be stream.[[writer]].
  3134. auto writer = stream.writer();
  3135. // 4. If writer is not undefined and backpressure is not stream.[[backpressure]],
  3136. if (writer && backpressure != stream.backpressure()) {
  3137. // 1. If backpressure is true, set writer.[[readyPromise]] to a new promise.
  3138. if (backpressure) {
  3139. writer->set_ready_promise(WebIDL::create_promise(realm));
  3140. }
  3141. // 2. Otherwise,
  3142. else {
  3143. // 1. Assert: backpressure is false.
  3144. // 2. Resolve writer.[[readyPromise]] with undefined.
  3145. WebIDL::resolve_promise(realm, *writer->ready_promise(), JS::js_undefined());
  3146. }
  3147. }
  3148. // 5. Set stream.[[backpressure]] to backpressure.
  3149. stream.set_backpressure(backpressure);
  3150. }
  3151. // https://streams.spec.whatwg.org/#writable-stream-default-writer-abort
  3152. GC::Ref<WebIDL::Promise> writable_stream_default_writer_abort(WritableStreamDefaultWriter& writer, JS::Value reason)
  3153. {
  3154. // 1. Let stream be writer.[[stream]].
  3155. auto stream = writer.stream();
  3156. // 2. Assert: stream is not undefined.
  3157. VERIFY(stream);
  3158. // 3. Return ! WritableStreamAbort(stream, reason).
  3159. return writable_stream_abort(*stream, reason);
  3160. }
  3161. // https://streams.spec.whatwg.org/#writable-stream-default-writer-close
  3162. GC::Ref<WebIDL::Promise> writable_stream_default_writer_close(WritableStreamDefaultWriter& writer)
  3163. {
  3164. // 1. Let stream be writer.[[stream]].
  3165. auto stream = writer.stream();
  3166. // 2. Assert: stream is not undefined.
  3167. VERIFY(stream);
  3168. // 3. Return ! WritableStreamClose(stream).
  3169. return writable_stream_close(*stream);
  3170. }
  3171. // https://streams.spec.whatwg.org/#writable-stream-default-writer-ensure-closed-promise-rejected
  3172. void writable_stream_default_writer_ensure_closed_promise_rejected(WritableStreamDefaultWriter& writer, JS::Value error)
  3173. {
  3174. auto& realm = writer.realm();
  3175. // 1. If writer.[[closedPromise]].[[PromiseState]] is "pending", reject writer.[[closedPromise]] with error.
  3176. auto& closed_promise = verify_cast<JS::Promise>(*writer.closed_promise()->promise());
  3177. if (closed_promise.state() == JS::Promise::State::Pending) {
  3178. WebIDL::reject_promise(realm, *writer.closed_promise(), error);
  3179. }
  3180. // 2. Otherwise, set writer.[[closedPromise]] to a promise rejected with error.
  3181. else {
  3182. writer.set_closed_promise(WebIDL::create_rejected_promise(realm, error));
  3183. }
  3184. // 3. Set writer.[[closedPromise]].[[PromiseIsHandled]] to true.
  3185. WebIDL::mark_promise_as_handled(*writer.closed_promise());
  3186. }
  3187. // https://streams.spec.whatwg.org/#writable-stream-default-writer-ensure-ready-promise-rejected
  3188. void writable_stream_default_writer_ensure_ready_promise_rejected(WritableStreamDefaultWriter& writer, JS::Value error)
  3189. {
  3190. auto& realm = writer.realm();
  3191. // 1. If writer.[[readyPromise]].[[PromiseState]] is "pending", reject writer.[[readyPromise]] with error.
  3192. auto& ready_promise = verify_cast<JS::Promise>(*writer.ready_promise()->promise());
  3193. if (ready_promise.state() == JS::Promise::State::Pending) {
  3194. WebIDL::reject_promise(realm, *writer.ready_promise(), error);
  3195. }
  3196. // 2. Otherwise, set writer.[[readyPromise]] to a promise rejected with error.
  3197. else {
  3198. writer.set_ready_promise(WebIDL::create_rejected_promise(realm, error));
  3199. }
  3200. // 3. Set writer.[[readyPromise]].[[PromiseIsHandled]] to true.
  3201. WebIDL::mark_promise_as_handled(*writer.ready_promise());
  3202. }
  3203. // https://streams.spec.whatwg.org/#writable-stream-default-writer-get-desired-size
  3204. Optional<double> writable_stream_default_writer_get_desired_size(WritableStreamDefaultWriter const& writer)
  3205. {
  3206. // 1. Let stream be writer.[[stream]].
  3207. auto stream = writer.stream();
  3208. // 2. Let state be stream.[[state]].
  3209. auto state = stream->state();
  3210. // 3. If state is "errored" or "erroring", return null.
  3211. if (state == WritableStream::State::Errored || state == WritableStream::State::Erroring)
  3212. return {};
  3213. // 4. If state is "closed", return 0.
  3214. if (state == WritableStream::State::Closed)
  3215. return 0.0;
  3216. // 5. Return ! WritableStreamDefaultControllerGetDesiredSize(stream.[[controller]]).
  3217. return writable_stream_default_controller_get_desired_size(*stream->controller());
  3218. }
  3219. // https://streams.spec.whatwg.org/#writable-stream-default-writer-release
  3220. void writable_stream_default_writer_release(WritableStreamDefaultWriter& writer)
  3221. {
  3222. auto& realm = writer.realm();
  3223. // 1. Let stream be writer.[[stream]].
  3224. auto stream = writer.stream();
  3225. // 2. Assert: stream is not undefined.
  3226. VERIFY(stream);
  3227. // 3. Assert: stream.[[writer]] is writer.
  3228. VERIFY(stream->writer().ptr() == &writer);
  3229. // 4. Let releasedError be a new TypeError.
  3230. auto released_error = JS::TypeError::create(realm, "Writer's stream lock has been released"sv);
  3231. // 5. Perform ! WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError).
  3232. writable_stream_default_writer_ensure_ready_promise_rejected(writer, released_error);
  3233. // 6. Perform ! WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedError).
  3234. writable_stream_default_writer_ensure_closed_promise_rejected(writer, released_error);
  3235. // 7. Set stream.[[writer]] to undefined.
  3236. stream->set_writer({});
  3237. // 8. Set writer.[[stream]] to undefined.
  3238. writer.set_stream({});
  3239. }
  3240. // https://streams.spec.whatwg.org/#writable-stream-default-writer-write
  3241. GC::Ref<WebIDL::Promise> writable_stream_default_writer_write(WritableStreamDefaultWriter& writer, JS::Value chunk)
  3242. {
  3243. auto& realm = writer.realm();
  3244. // 1. Let stream be writer.[[stream]].
  3245. auto stream = writer.stream();
  3246. // 2. Assert: stream is not undefined.
  3247. VERIFY(stream);
  3248. // 3. Let controller be stream.[[controller]].
  3249. auto controller = stream->controller();
  3250. // 4. Let chunkSize be ! WritableStreamDefaultControllerGetChunkSize(controller, chunk).
  3251. auto chunk_size = writable_stream_default_controller_get_chunk_size(*controller, chunk);
  3252. // 5. If stream is not equal to writer.[[stream]], return a promise rejected with a TypeError exception.
  3253. if (stream.ptr() != writer.stream().ptr()) {
  3254. auto exception = JS::TypeError::create(realm, "Writer's locked stream changed during write"sv);
  3255. return WebIDL::create_rejected_promise(realm, exception);
  3256. }
  3257. // 6. Let state be stream.[[state]].
  3258. auto state = stream->state();
  3259. // 7. If state is "errored", return a promise rejected with stream.[[storedError]].
  3260. if (state == WritableStream::State::Errored)
  3261. return WebIDL::create_rejected_promise(realm, stream->stored_error());
  3262. // 8. If ! WritableStreamCloseQueuedOrInFlight(stream) is true or state is "closed", return a promise rejected with a TypeError exception indicating that the stream is closing or closed.
  3263. if (writable_stream_close_queued_or_in_flight(*stream) || state == WritableStream::State::Closed) {
  3264. auto exception = JS::TypeError::create(realm, "Cannot write to a writer whose stream is closing or already closed"sv);
  3265. return WebIDL::create_rejected_promise(realm, exception);
  3266. }
  3267. // 9. If state is "erroring", return a promise rejected with stream.[[storedError]].
  3268. if (state == WritableStream::State::Erroring)
  3269. return WebIDL::create_rejected_promise(realm, stream->stored_error());
  3270. // 10. Assert: state is "writable".
  3271. VERIFY(state == WritableStream::State::Writable);
  3272. // 11. Let promise be ! WritableStreamAddWriteRequest(stream).
  3273. auto promise = writable_stream_add_write_request(*stream);
  3274. // 12. Perform ! WritableStreamDefaultControllerWrite(controller, chunk, chunkSize).
  3275. writable_stream_default_controller_write(*controller, chunk, chunk_size);
  3276. // 13. Return promise.
  3277. return promise;
  3278. }
  3279. // https://streams.spec.whatwg.org/#set-up-writable-stream-default-controller
  3280. WebIDL::ExceptionOr<void> set_up_writable_stream_default_controller(WritableStream& stream, WritableStreamDefaultController& controller, GC::Ref<StartAlgorithm> start_algorithm, GC::Ref<WriteAlgorithm> write_algorithm, GC::Ref<CloseAlgorithm> close_algorithm, GC::Ref<AbortAlgorithm> abort_algorithm, double high_water_mark, GC::Ref<SizeAlgorithm> size_algorithm)
  3281. {
  3282. auto& realm = stream.realm();
  3283. // 1. Assert: stream implements WritableStream.
  3284. // 2. Assert: stream.[[controller]] is undefined.
  3285. VERIFY(!stream.controller());
  3286. // 3. Set controller.[[stream]] to stream.
  3287. controller.set_stream(stream);
  3288. // 4. Set stream.[[controller]] to controller.
  3289. stream.set_controller(controller);
  3290. // 5. Perform ! ResetQueue(controller).
  3291. reset_queue(controller);
  3292. // 6. Set controller.[[signal]] to a new AbortSignal.
  3293. controller.set_signal(realm.create<DOM::AbortSignal>(realm));
  3294. // 7. Set controller.[[started]] to false.
  3295. controller.set_started(false);
  3296. // 8. Set controller.[[strategySizeAlgorithm]] to sizeAlgorithm.
  3297. controller.set_strategy_size_algorithm(size_algorithm);
  3298. // 9. Set controller.[[strategyHWM]] to highWaterMark.
  3299. controller.set_strategy_hwm(high_water_mark);
  3300. // 10. Set controller.[[writeAlgorithm]] to writeAlgorithm.
  3301. controller.set_write_algorithm(write_algorithm);
  3302. // 11. Set controller.[[closeAlgorithm]] to closeAlgorithm.
  3303. controller.set_close_algorithm(close_algorithm);
  3304. // 12. Set controller.[[abortAlgorithm]] to abortAlgorithm.
  3305. controller.set_abort_algorithm(abort_algorithm);
  3306. // 13. Let backpressure be ! WritableStreamDefaultControllerGetBackpressure(controller).
  3307. auto backpressure = writable_stream_default_controller_get_backpressure(controller);
  3308. // 14. Perform ! WritableStreamUpdateBackpressure(stream, backpressure).
  3309. writable_stream_update_backpressure(stream, backpressure);
  3310. // 15. Let startResult be the result of performing startAlgorithm. (This may throw an exception.)
  3311. auto start_result = TRY(start_algorithm->function()());
  3312. // 16. Let startPromise be a promise resolved with startResult.
  3313. auto start_promise = WebIDL::create_resolved_promise(realm, start_result);
  3314. // 17. Upon fulfillment of startPromise,
  3315. WebIDL::upon_fulfillment(*start_promise, GC::create_function(realm.heap(), [&controller, &stream](JS::Value) -> WebIDL::ExceptionOr<JS::Value> {
  3316. // 1. Assert: stream.[[state]] is "writable" or "erroring".
  3317. auto state = stream.state();
  3318. VERIFY(state == WritableStream::State::Writable || state == WritableStream::State::Erroring);
  3319. // 2. Set controller.[[started]] to true.
  3320. controller.set_started(true);
  3321. // 3. Perform ! WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller).
  3322. writable_stream_default_controller_advance_queue_if_needed(controller);
  3323. return JS::js_undefined();
  3324. }));
  3325. // 18. Upon rejection of startPromise with reason r,
  3326. WebIDL::upon_rejection(*start_promise, GC::create_function(realm.heap(), [&stream, &controller](JS::Value reason) -> WebIDL::ExceptionOr<JS::Value> {
  3327. // 1. Assert: stream.[[state]] is "writable" or "erroring".
  3328. auto state = stream.state();
  3329. VERIFY(state == WritableStream::State::Writable || state == WritableStream::State::Erroring);
  3330. // 2. Set controller.[[started]] to true.
  3331. controller.set_started(true);
  3332. // 3. Perform ! WritableStreamDealWithRejection(stream, r).
  3333. writable_stream_deal_with_rejection(stream, reason);
  3334. return JS::js_undefined();
  3335. }));
  3336. return {};
  3337. }
  3338. // https://streams.spec.whatwg.org/#set-up-writable-stream-default-controller-from-underlying-sink
  3339. WebIDL::ExceptionOr<void> set_up_writable_stream_default_controller_from_underlying_sink(WritableStream& stream, JS::Value underlying_sink_value, UnderlyingSink& underlying_sink, double high_water_mark, GC::Ref<SizeAlgorithm> size_algorithm)
  3340. {
  3341. auto& realm = stream.realm();
  3342. // 1. Let controller be a new WritableStreamDefaultController.
  3343. auto controller = realm.create<WritableStreamDefaultController>(realm);
  3344. // 2. Let startAlgorithm be an algorithm that returns undefined.
  3345. auto start_algorithm = GC::create_function(realm.heap(), []() -> WebIDL::ExceptionOr<JS::Value> { return JS::js_undefined(); });
  3346. // 3. Let writeAlgorithm be an algorithm that returns a promise resolved with undefined.
  3347. auto write_algorithm = GC::create_function(realm.heap(), [&realm](JS::Value) {
  3348. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  3349. });
  3350. // 4. Let closeAlgorithm be an algorithm that returns a promise resolved with undefined.
  3351. auto close_algorithm = GC::create_function(realm.heap(), [&realm]() {
  3352. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  3353. });
  3354. // 5. Let abortAlgorithm be an algorithm that returns a promise resolved with undefined.
  3355. auto abort_algorithm = GC::create_function(realm.heap(), [&realm](JS::Value) {
  3356. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  3357. });
  3358. // 6. If underlyingSinkDict["start"] exists, then set startAlgorithm to an algorithm which returns the result of invoking underlyingSinkDict["start"] with argument list « controller » and callback this value underlyingSink.
  3359. if (underlying_sink.start) {
  3360. start_algorithm = GC::create_function(realm.heap(), [controller, underlying_sink_value, callback = underlying_sink.start]() -> WebIDL::ExceptionOr<JS::Value> {
  3361. // Note: callback does not return a promise, so invoke_callback may return an abrupt completion
  3362. return TRY(WebIDL::invoke_callback(*callback, underlying_sink_value, controller)).release_value();
  3363. });
  3364. }
  3365. // 7. If underlyingSinkDict["write"] exists, then set writeAlgorithm to an algorithm which takes an argument chunk and returns the result of invoking underlyingSinkDict["write"] with argument list « chunk, controller » and callback this value underlyingSink.
  3366. if (underlying_sink.write) {
  3367. write_algorithm = GC::create_function(realm.heap(), [&realm, controller, underlying_sink_value, callback = underlying_sink.write](JS::Value chunk) {
  3368. // Note: callback returns a promise, so invoke_callback will never return an abrupt completion
  3369. auto result = MUST(WebIDL::invoke_callback(*callback, underlying_sink_value, chunk, controller)).release_value();
  3370. return WebIDL::create_resolved_promise(realm, result);
  3371. });
  3372. }
  3373. // 8. If underlyingSinkDict["close"] exists, then set closeAlgorithm to an algorithm which returns the result of invoking underlyingSinkDict["close"] with argument list «» and callback this value underlyingSink.
  3374. if (underlying_sink.close) {
  3375. close_algorithm = GC::create_function(realm.heap(), [&realm, underlying_sink_value, callback = underlying_sink.close]() {
  3376. // Note: callback returns a promise, so invoke_callback will never return an abrupt completion
  3377. auto result = MUST(WebIDL::invoke_callback(*callback, underlying_sink_value)).release_value();
  3378. return WebIDL::create_resolved_promise(realm, result);
  3379. });
  3380. }
  3381. // 9. If underlyingSinkDict["abort"] exists, then set abortAlgorithm to an algorithm which takes an argument reason and returns the result of invoking underlyingSinkDict["abort"] with argument list « reason » and callback this value underlyingSink.
  3382. if (underlying_sink.abort) {
  3383. abort_algorithm = GC::create_function(realm.heap(), [&realm, underlying_sink_value, callback = underlying_sink.abort](JS::Value reason) {
  3384. // Note: callback returns a promise, so invoke_callback will never return an abrupt completion
  3385. auto result = MUST(WebIDL::invoke_callback(*callback, underlying_sink_value, reason)).release_value();
  3386. return WebIDL::create_resolved_promise(realm, result);
  3387. });
  3388. }
  3389. // 10. Perform ? SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm).
  3390. TRY(set_up_writable_stream_default_controller(stream, controller, start_algorithm, write_algorithm, close_algorithm, abort_algorithm, high_water_mark, size_algorithm));
  3391. return {};
  3392. }
  3393. // https://streams.spec.whatwg.org/#writable-stream-default-controller-advance-queue-if-needed
  3394. void writable_stream_default_controller_advance_queue_if_needed(WritableStreamDefaultController& controller)
  3395. {
  3396. // 1. Let stream be controller.[[stream]].
  3397. auto stream = controller.stream();
  3398. // 2. If controller.[[started]] is false, return.
  3399. if (!controller.started())
  3400. return;
  3401. // 3. If stream.[[inFlightWriteRequest]] is not undefined, return.
  3402. if (stream->in_flight_write_request())
  3403. return;
  3404. // 4. Let state be stream.[[state]].
  3405. auto state = stream->state();
  3406. // 5. Assert: state is not "closed" or "errored".
  3407. VERIFY(state != WritableStream::State::Closed && state != WritableStream::State::Errored);
  3408. // 6. If state is "erroring",
  3409. if (state == WritableStream::State::Erroring) {
  3410. // 1. Perform ! WritableStreamFinishErroring(stream).
  3411. writable_stream_finish_erroring(*stream);
  3412. // 2. Return.
  3413. return;
  3414. }
  3415. // 7. If controller.[[queue]] is empty, return.
  3416. if (controller.queue().is_empty())
  3417. return;
  3418. // 8. Let value be ! PeekQueueValue(controller).
  3419. auto value = peek_queue_value(controller);
  3420. // 9. If value is the close sentinel, perform ! WritableStreamDefaultControllerProcessClose(controller).
  3421. if (is_close_sentinel(value)) {
  3422. writable_stream_default_controller_process_close(controller);
  3423. }
  3424. // 10. Otherwise, perform ! WritableStreamDefaultControllerProcessWrite(controller, value).
  3425. else {
  3426. writable_stream_default_controller_process_write(controller, value);
  3427. }
  3428. }
  3429. // https://streams.spec.whatwg.org/#writable-stream-default-controller-clear-algorithms
  3430. void writable_stream_default_controller_clear_algorithms(WritableStreamDefaultController& controller)
  3431. {
  3432. // 1. Set controller.[[writeAlgorithm]] to undefined.
  3433. controller.set_write_algorithm({});
  3434. // 2. Set controller.[[closeAlgorithm]] to undefined.
  3435. controller.set_close_algorithm({});
  3436. // 3. Set controller.[[abortAlgorithm]] to undefined.
  3437. controller.set_abort_algorithm({});
  3438. // 4. Set controller.[[strategySizeAlgorithm]] to undefined.
  3439. controller.set_strategy_size_algorithm({});
  3440. }
  3441. // https://streams.spec.whatwg.org/#writable-stream-default-controller-close
  3442. void writable_stream_default_controller_close(WritableStreamDefaultController& controller)
  3443. {
  3444. // 1. Perform ! EnqueueValueWithSize(controller, close sentinel, 0).
  3445. MUST(enqueue_value_with_size(controller, create_close_sentinel(), JS::Value(0.0)));
  3446. // 2. Perform ! WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller).
  3447. writable_stream_default_controller_advance_queue_if_needed(controller);
  3448. }
  3449. // https://streams.spec.whatwg.org/#writable-stream-default-controller-error
  3450. void writable_stream_default_controller_error(WritableStreamDefaultController& controller, JS::Value error)
  3451. {
  3452. // 1. Let stream be controller.[[stream]].
  3453. auto stream = controller.stream();
  3454. // 2. Assert: stream.[[state]] is "writable".
  3455. VERIFY(stream->state() == WritableStream::State::Writable);
  3456. // 3. Perform ! WritableStreamDefaultControllerClearAlgorithms(controller).
  3457. writable_stream_default_controller_clear_algorithms(controller);
  3458. // 4. Perform ! WritableStreamStartErroring(stream, error).
  3459. writable_stream_start_erroring(stream, error);
  3460. }
  3461. // https://streams.spec.whatwg.org/#writable-stream-default-controller-error-if-needed
  3462. void writable_stream_default_controller_error_if_needed(WritableStreamDefaultController& controller, JS::Value error)
  3463. {
  3464. // 1. If controller.[[stream]].[[state]] is "writable", perform ! WritableStreamDefaultControllerError(controller, error).
  3465. if (controller.stream()->state() == WritableStream::State::Writable)
  3466. writable_stream_default_controller_error(controller, error);
  3467. }
  3468. // https://streams.spec.whatwg.org/#writable-stream-default-controller-get-backpressure
  3469. bool writable_stream_default_controller_get_backpressure(WritableStreamDefaultController const& controller)
  3470. {
  3471. // 1. Let desiredSize be ! WritableStreamDefaultControllerGetDesiredSize(controller).
  3472. auto desired_size = writable_stream_default_controller_get_desired_size(controller);
  3473. // 2. Return true if desiredSize ≤ 0, or false otherwise.
  3474. return desired_size <= 0.0;
  3475. }
  3476. // https://streams.spec.whatwg.org/#writable-stream-default-controller-get-chunk-size
  3477. JS::Value writable_stream_default_controller_get_chunk_size(WritableStreamDefaultController& controller, JS::Value chunk)
  3478. {
  3479. // 1. If controller.[[strategySizeAlgorithm]] is undefined, then:
  3480. if (!controller.strategy_size_algorithm()) {
  3481. // 1. Assert: controller.[[stream]].[[state]] is "erroring" or "errored".
  3482. VERIFY(controller.stream()->state() == WritableStream::State::Erroring || controller.stream()->state() == WritableStream::State::Errored);
  3483. // 2. Return 1.
  3484. return JS::Value { 1.0 };
  3485. }
  3486. // 2. Let returnValue be the result of performing controller.[[strategySizeAlgorithm]], passing in chunk, and interpreting the result as a completion record.
  3487. auto return_value = controller.strategy_size_algorithm()->function()(chunk);
  3488. // 3. If returnValue is an abrupt completion,
  3489. if (return_value.is_abrupt()) {
  3490. // 1. Perform ! WritableStreamDefaultControllerErrorIfNeeded(controller, returnValue.[[Value]]).
  3491. writable_stream_default_controller_error_if_needed(controller, *return_value.release_value());
  3492. // 2. Return 1.
  3493. return JS::Value { 1.0 };
  3494. }
  3495. // 4. Return returnValue.[[Value]].
  3496. return *return_value.release_value();
  3497. }
  3498. // https://streams.spec.whatwg.org/#writable-stream-default-controller-get-desired-size
  3499. double writable_stream_default_controller_get_desired_size(WritableStreamDefaultController const& controller)
  3500. {
  3501. // 1. Return controller.[[strategyHWM]] − controller.[[queueTotalSize]].
  3502. return controller.strategy_hwm() - controller.queue_total_size();
  3503. }
  3504. // https://streams.spec.whatwg.org/#writable-stream-default-controller-process-close
  3505. void writable_stream_default_controller_process_close(WritableStreamDefaultController& controller)
  3506. {
  3507. // 1. Let stream be controller.[[stream]].
  3508. auto stream = controller.stream();
  3509. // 2. Perform ! WritableStreamMarkCloseRequestInFlight(stream).
  3510. writable_stream_mark_close_request_in_flight(*stream);
  3511. // 3. Perform ! DequeueValue(controller).
  3512. dequeue_value(controller);
  3513. // 4. Assert: controller.[[queue]] is empty.
  3514. VERIFY(controller.queue().is_empty());
  3515. // 5. Let sinkClosePromise be the result of performing controller.[[closeAlgorithm]].
  3516. auto sink_close_promise = controller.close_algorithm()->function()();
  3517. // 6. Perform ! WritableStreamDefaultControllerClearAlgorithms(controller).
  3518. writable_stream_default_controller_clear_algorithms(controller);
  3519. // 7. Upon fulfillment of sinkClosePromise,
  3520. WebIDL::upon_fulfillment(*sink_close_promise, GC::create_function(controller.heap(), [stream](JS::Value) -> WebIDL::ExceptionOr<JS::Value> {
  3521. // 1. Perform ! WritableStreamFinishInFlightClose(stream).
  3522. writable_stream_finish_in_flight_close(*stream);
  3523. return JS::js_undefined();
  3524. }));
  3525. // 8. Upon rejection of sinkClosePromise with reason reason,
  3526. WebIDL::upon_rejection(*sink_close_promise, GC::create_function(controller.heap(), [stream = stream](JS::Value reason) -> WebIDL::ExceptionOr<JS::Value> {
  3527. // 1. Perform ! WritableStreamFinishInFlightCloseWithError(stream, reason).
  3528. writable_stream_finish_in_flight_close_with_error(*stream, reason);
  3529. return JS::js_undefined();
  3530. }));
  3531. }
  3532. // https://streams.spec.whatwg.org/#writable-stream-default-controller-process-write
  3533. void writable_stream_default_controller_process_write(WritableStreamDefaultController& controller, JS::Value chunk)
  3534. {
  3535. // 1. Let stream be controller.[[stream]].
  3536. auto stream = controller.stream();
  3537. // 2. Perform ! WritableStreamMarkFirstWriteRequestInFlight(stream).
  3538. writable_stream_mark_first_write_request_in_flight(*stream);
  3539. // 3. Let sinkWritePromise be the result of performing controller.[[writeAlgorithm]], passing in chunk.
  3540. auto sink_write_promise = controller.write_algorithm()->function()(chunk);
  3541. // 4. Upon fulfillment of sinkWritePromise,
  3542. WebIDL::upon_fulfillment(*sink_write_promise, GC::create_function(controller.heap(), [&controller, stream](JS::Value) -> WebIDL::ExceptionOr<JS::Value> {
  3543. // 1. Perform ! WritableStreamFinishInFlightWrite(stream).
  3544. writable_stream_finish_in_flight_write(*stream);
  3545. // 2. Let state be stream.[[state]].
  3546. auto state = stream->state();
  3547. // 3. Assert: state is "writable" or "erroring".
  3548. VERIFY(state == WritableStream::State::Writable || state == WritableStream::State::Erroring);
  3549. // 4. Perform ! DequeueValue(controller).
  3550. dequeue_value(controller);
  3551. // 5. If ! WritableStreamCloseQueuedOrInFlight(stream) is false and state is "writable",
  3552. if (!writable_stream_close_queued_or_in_flight(*stream) && state == WritableStream::State::Writable) {
  3553. // 1. Let backpressure be ! WritableStreamDefaultControllerGetBackpressure(controller).
  3554. auto backpressure = writable_stream_default_controller_get_backpressure(controller);
  3555. // 2. Perform ! WritableStreamUpdateBackpressure(stream, backpressure).
  3556. writable_stream_update_backpressure(*stream, backpressure);
  3557. }
  3558. // 6 .Perform ! WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller).
  3559. writable_stream_default_controller_advance_queue_if_needed(controller);
  3560. return JS::js_undefined();
  3561. }));
  3562. // 5. Upon rejection of sinkWritePromise with reason,
  3563. WebIDL::upon_rejection(*sink_write_promise, GC::create_function(controller.heap(), [&controller, stream](JS::Value reason) -> WebIDL::ExceptionOr<JS::Value> {
  3564. // 1. If stream.[[state]] is "writable", perform ! WritableStreamDefaultControllerClearAlgorithms(controller).
  3565. if (stream->state() == WritableStream::State::Writable)
  3566. writable_stream_default_controller_clear_algorithms(controller);
  3567. // 2. Perform ! WritableStreamFinishInFlightWriteWithError(stream, reason).
  3568. writable_stream_finish_in_flight_write_with_error(*stream, reason);
  3569. return JS::js_undefined();
  3570. }));
  3571. }
  3572. // https://streams.spec.whatwg.org/#writable-stream-default-controller-write
  3573. void writable_stream_default_controller_write(WritableStreamDefaultController& controller, JS::Value chunk, JS::Value chunk_size)
  3574. {
  3575. auto& vm = controller.vm();
  3576. // 1. Let enqueueResult be EnqueueValueWithSize(controller, chunk, chunkSize).
  3577. auto enqueue_result = enqueue_value_with_size(controller, chunk, chunk_size);
  3578. // 2. If enqueueResult is an abrupt completion,
  3579. if (enqueue_result.is_exception()) {
  3580. auto throw_completion = Bindings::throw_dom_exception_if_needed(vm, [&] { return enqueue_result; }).throw_completion();
  3581. // 1. Perform ! WritableStreamDefaultControllerErrorIfNeeded(controller, enqueueResult.[[Value]]).
  3582. writable_stream_default_controller_error_if_needed(controller, *throw_completion.release_value());
  3583. // 2. Return.
  3584. return;
  3585. }
  3586. // 3. Let stream be controller.[[stream]].
  3587. auto stream = controller.stream();
  3588. // 4. If ! WritableStreamCloseQueuedOrInFlight(stream) is false and stream.[[state]] is "writable",
  3589. if (!writable_stream_close_queued_or_in_flight(*stream) && stream->state() == WritableStream::State::Writable) {
  3590. // 1. Let backpressure be ! WritableStreamDefaultControllerGetBackpressure(controller).
  3591. auto backpressure = writable_stream_default_controller_get_backpressure(controller);
  3592. // 2. Perform ! WritableStreamUpdateBackpressure(stream, backpressure).
  3593. writable_stream_update_backpressure(*stream, backpressure);
  3594. }
  3595. // 5. Perform ! WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller).
  3596. writable_stream_default_controller_advance_queue_if_needed(controller);
  3597. }
  3598. // https://streams.spec.whatwg.org/#initialize-transform-stream
  3599. void initialize_transform_stream(TransformStream& stream, GC::Ref<WebIDL::Promise> start_promise, double writable_high_water_mark, GC::Ref<SizeAlgorithm> writable_size_algorithm, double readable_high_water_mark, GC::Ref<SizeAlgorithm> readable_size_algorithm)
  3600. {
  3601. auto& realm = stream.realm();
  3602. // 1. Let startAlgorithm be an algorithm that returns startPromise.
  3603. auto writable_start_algorithm = GC::create_function(realm.heap(), [start_promise]() -> WebIDL::ExceptionOr<JS::Value> {
  3604. return start_promise->promise();
  3605. });
  3606. auto readable_start_algorithm = GC::create_function(realm.heap(), [start_promise]() -> WebIDL::ExceptionOr<JS::Value> {
  3607. return start_promise->promise();
  3608. });
  3609. // 2. Let writeAlgorithm be the following steps, taking a chunk argument:
  3610. auto write_algorithm = GC::create_function(realm.heap(), [&stream](JS::Value chunk) {
  3611. // 1. Return ! TransformStreamDefaultSinkWriteAlgorithm(stream, chunk).
  3612. return transform_stream_default_sink_write_algorithm(stream, chunk);
  3613. });
  3614. // 3. Let abortAlgorithm be the following steps, taking a reason argument:
  3615. auto abort_algorithm = GC::create_function(realm.heap(), [&stream](JS::Value reason) {
  3616. // 1. Return ! TransformStreamDefaultSinkAbortAlgorithm(stream, reason).
  3617. return transform_stream_default_sink_abort_algorithm(stream, reason);
  3618. });
  3619. // 4. Let closeAlgorithm be the following steps:
  3620. auto close_algorithm = GC::create_function(realm.heap(), [&stream]() {
  3621. // 1. Return ! TransformStreamDefaultSinkCloseAlgorithm(stream).
  3622. return transform_stream_default_sink_close_algorithm(stream);
  3623. });
  3624. // 5. Set stream.[[writable]] to ! CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, writableHighWaterMark, writableSizeAlgorithm).
  3625. stream.set_writable(MUST(create_writable_stream(realm, writable_start_algorithm, write_algorithm, close_algorithm, abort_algorithm, writable_high_water_mark, writable_size_algorithm)));
  3626. // 6. Let pullAlgorithm be the following steps:
  3627. auto pull_algorithm = GC::create_function(realm.heap(), [&stream]() {
  3628. // 1. Return ! TransformStreamDefaultSourcePullAlgorithm(stream).
  3629. return transform_stream_default_source_pull_algorithm(stream);
  3630. });
  3631. // 7. Let cancelAlgorithm be the following steps, taking a reason argument:
  3632. auto cancel_algorithm = GC::create_function(realm.heap(), [&stream](JS::Value reason) {
  3633. // 1. Return ! TransformStreamDefaultSourceCancelAlgorithm(stream, reason).
  3634. return transform_stream_default_source_cancel_algorithm(stream, reason);
  3635. });
  3636. // 8. Set stream.[[readable]] to ! CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, readableHighWaterMark, readableSizeAlgorithm).
  3637. stream.set_readable(MUST(create_readable_stream(realm, readable_start_algorithm, pull_algorithm, cancel_algorithm, readable_high_water_mark, readable_size_algorithm)));
  3638. // 9. Set stream.[[backpressure]] and stream.[[backpressureChangePromise]] to undefined.
  3639. stream.set_backpressure({});
  3640. stream.set_backpressure_change_promise({});
  3641. // 10. Perform ! TransformStreamSetBackpressure(stream, true).
  3642. transform_stream_set_backpressure(stream, true);
  3643. // 11. Set stream.[[controller]] to undefined.
  3644. stream.set_controller({});
  3645. }
  3646. // https://streams.spec.whatwg.org/#set-up-transform-stream-default-controller
  3647. void set_up_transform_stream_default_controller(TransformStream& stream, TransformStreamDefaultController& controller, GC::Ref<TransformAlgorithm> transform_algorithm, GC::Ref<FlushAlgorithm> flush_algorithm, GC::Ref<CancelAlgorithm> cancel_algorithm)
  3648. {
  3649. // 1. Assert: stream implements TransformStream.
  3650. // 2. Assert: stream.[[controller]] is undefined.
  3651. VERIFY(!stream.controller());
  3652. // 3. Set controller.[[stream]] to stream.
  3653. controller.set_stream(stream);
  3654. // 4. Set stream.[[controller]] to controller.
  3655. stream.set_controller(controller);
  3656. // 5. Set controller.[[transformAlgorithm]] to transformAlgorithm.
  3657. controller.set_transform_algorithm(transform_algorithm);
  3658. // 6. Set controller.[[flushAlgorithm]] to flushAlgorithm.
  3659. controller.set_flush_algorithm(flush_algorithm);
  3660. // 7. Set controller.[[cancelAlgorithm]] to cancelAlgorithm.
  3661. controller.set_cancel_algorithm(cancel_algorithm);
  3662. }
  3663. // https://streams.spec.whatwg.org/#set-up-transform-stream-default-controller-from-transformer
  3664. void set_up_transform_stream_default_controller_from_transformer(TransformStream& stream, JS::Value transformer, Transformer& transformer_dict)
  3665. {
  3666. auto& realm = stream.realm();
  3667. auto& vm = realm.vm();
  3668. // 1. Let controller be a new TransformStreamDefaultController.
  3669. auto controller = realm.create<TransformStreamDefaultController>(realm);
  3670. // 2. Let transformAlgorithm be the following steps, taking a chunk argument:
  3671. auto transform_algorithm = GC::create_function(realm.heap(), [controller, &realm, &vm](JS::Value chunk) {
  3672. // 1. Let result be TransformStreamDefaultControllerEnqueue(controller, chunk).
  3673. auto result = transform_stream_default_controller_enqueue(*controller, chunk);
  3674. // 2. If result is an abrupt completion, return a promise rejected with result.[[Value]].
  3675. if (result.is_error()) {
  3676. auto throw_completion = Bindings::exception_to_throw_completion(vm, result.exception());
  3677. return WebIDL::create_rejected_promise(realm, *throw_completion.release_value());
  3678. }
  3679. // 3. Otherwise, return a promise resolved with undefined.
  3680. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  3681. });
  3682. // 3. Let flushAlgorithm be an algorithm which returns a promise resolved with undefined.
  3683. auto flush_algorithm = GC::create_function(realm.heap(), [&realm]() {
  3684. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  3685. });
  3686. // 4. Let cancelAlgorithm be an algorithm which returns a promise resolved with undefined.
  3687. auto cancel_algorithm = GC::create_function(realm.heap(), [&realm](JS::Value) {
  3688. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  3689. });
  3690. // 5. If transformerDict["transform"] exists, set transformAlgorithm to an algorithm which takes an argument chunk
  3691. // and returns the result of invoking transformerDict["transform"] with argument list « chunk, controller » and
  3692. // callback this value transformer.
  3693. if (transformer_dict.transform) {
  3694. transform_algorithm = GC::create_function(realm.heap(), [controller, &realm, transformer, callback = transformer_dict.transform](JS::Value chunk) {
  3695. // Note: callback returns a promise, so invoke_callback will never return an abrupt completion
  3696. auto result = MUST(WebIDL::invoke_callback(*callback, transformer, chunk, controller)).release_value();
  3697. return WebIDL::create_resolved_promise(realm, result);
  3698. });
  3699. }
  3700. // 6. If transformerDict["flush"] exists, set flushAlgorithm to an algorithm which returns the result of invoking
  3701. // transformerDict["flush"] with argument list « controller » and callback this value transformer.
  3702. if (transformer_dict.flush) {
  3703. flush_algorithm = GC::create_function(realm.heap(), [&realm, transformer, callback = transformer_dict.flush, controller]() {
  3704. // Note: callback returns a promise, so invoke_callback will never return an abrupt completion
  3705. auto result = MUST(WebIDL::invoke_callback(*callback, transformer, controller)).release_value();
  3706. return WebIDL::create_resolved_promise(realm, result);
  3707. });
  3708. }
  3709. // 7. If transformerDict["cancel"] exists, set cancelAlgorithm to an algorithm which takes an argument reason and returns
  3710. // the result of invoking transformerDict["cancel"] with argument list « reason » and callback this value transformer.
  3711. if (transformer_dict.cancel) {
  3712. cancel_algorithm = GC::create_function(realm.heap(), [&realm, transformer, callback = transformer_dict.cancel](JS::Value reason) {
  3713. // Note: callback returns a promise, so invoke_callback will never return an abrupt completion
  3714. auto result = MUST(WebIDL::invoke_callback(*callback, transformer, reason)).release_value();
  3715. return WebIDL::create_resolved_promise(realm, result);
  3716. });
  3717. }
  3718. // 8. Perform ! SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm).
  3719. set_up_transform_stream_default_controller(stream, *controller, transform_algorithm, flush_algorithm, cancel_algorithm);
  3720. }
  3721. // https://streams.spec.whatwg.org/#transform-stream-default-controller-clear-algorithms
  3722. void transform_stream_default_controller_clear_algorithms(TransformStreamDefaultController& controller)
  3723. {
  3724. // NOTE: This is observable using weak references. See tc39/proposal-weakrefs#31 for more detail.
  3725. // 1. Set controller.[[transformAlgorithm]] to undefined.
  3726. controller.set_transform_algorithm({});
  3727. // 2. Set controller.[[flushAlgorithm]] to undefined.
  3728. controller.set_flush_algorithm({});
  3729. // 3. Set controller.[[cancelAlgorithm]] to undefined.
  3730. controller.set_cancel_algorithm({});
  3731. }
  3732. // https://streams.spec.whatwg.org/#transform-stream-default-controller-enqueue
  3733. WebIDL::ExceptionOr<void> transform_stream_default_controller_enqueue(TransformStreamDefaultController& controller, JS::Value chunk)
  3734. {
  3735. auto& vm = controller.vm();
  3736. // 1. Let stream be controller.[[stream]].
  3737. auto stream = controller.stream();
  3738. // 2. Let readableController be stream.[[readable]].[[controller]].
  3739. VERIFY(stream->readable()->controller().has_value() && stream->readable()->controller()->has<GC::Ref<ReadableStreamDefaultController>>());
  3740. auto& readable_controller = stream->readable()->controller()->get<GC::Ref<ReadableStreamDefaultController>>();
  3741. // 3. If ! ReadableStreamDefaultControllerCanCloseOrEnqueue(readableController) is false, throw a TypeError exception.
  3742. if (!readable_stream_default_controller_can_close_or_enqueue(readable_controller))
  3743. return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "ReadableController is either closed or not readable."sv };
  3744. // 4. Let enqueueResult be ReadableStreamDefaultControllerEnqueue(readableController, chunk).
  3745. auto enqueue_result = readable_stream_default_controller_enqueue(readable_controller, chunk);
  3746. // 5. If enqueueResult is an abrupt completion,
  3747. if (enqueue_result.is_error()) {
  3748. auto throw_completion = Bindings::exception_to_throw_completion(vm, enqueue_result.exception());
  3749. // 1. Perform ! TransformStreamErrorWritableAndUnblockWrite(stream, enqueueResult.[[Value]]).
  3750. transform_stream_error_writable_and_unblock_write(*stream, throw_completion.value().value());
  3751. // 2. Throw stream.[[readable]].[[storedError]].
  3752. return JS::throw_completion(stream->readable()->stored_error());
  3753. }
  3754. // 6. Let backpressure be ! ReadableStreamDefaultControllerHasBackpressure(readableController).
  3755. auto backpressure = readable_stream_default_controller_has_backpressure(readable_controller);
  3756. // 7. If backpressure is not stream.[[backpressure]],
  3757. if (backpressure != stream->backpressure()) {
  3758. // 1. Assert: backpressure is true.
  3759. VERIFY(backpressure);
  3760. // 2. Perform ! TransformStreamSetBackpressure(stream, true).
  3761. transform_stream_set_backpressure(*stream, true);
  3762. }
  3763. return {};
  3764. }
  3765. // https://streams.spec.whatwg.org/#transform-stream-default-controller-error
  3766. void transform_stream_default_controller_error(TransformStreamDefaultController& controller, JS::Value error)
  3767. {
  3768. // 1. Perform ! TransformStreamError(controller.[[stream]], e).
  3769. transform_stream_error(*controller.stream(), error);
  3770. }
  3771. // https://streams.spec.whatwg.org/#transform-stream-default-controller-terminate
  3772. void transform_stream_default_controller_terminate(TransformStreamDefaultController& controller)
  3773. {
  3774. auto& realm = controller.realm();
  3775. // 1. Let stream be controller.[[stream]].
  3776. auto stream = controller.stream();
  3777. // 2. Let readableController be stream.[[readable]].[[controller]].
  3778. VERIFY(stream->readable()->controller().has_value() && stream->readable()->controller()->has<GC::Ref<ReadableStreamDefaultController>>());
  3779. auto readable_controller = stream->readable()->controller()->get<GC::Ref<ReadableStreamDefaultController>>();
  3780. // 3. Perform ! ReadableStreamDefaultControllerClose(readableController).
  3781. readable_stream_default_controller_close(readable_controller);
  3782. // 4. Let error be a TypeError exception indicating that the stream has been terminated.
  3783. auto error = JS::TypeError::create(realm, "Stream has been terminated."sv);
  3784. // 5. Perform ! TransformStreamErrorWritableAndUnblockWrite(stream, error).
  3785. transform_stream_error_writable_and_unblock_write(*stream, error);
  3786. }
  3787. // https://streams.spec.whatwg.org/#transform-stream-default-controller-perform-transform
  3788. GC::Ref<WebIDL::Promise> transform_stream_default_controller_perform_transform(TransformStreamDefaultController& controller, JS::Value chunk)
  3789. {
  3790. auto& realm = controller.realm();
  3791. // 1. Let transformPromise be the result of performing controller.[[transformAlgorithm]], passing chunk.
  3792. auto transform_promise = controller.transform_algorithm()->function()(chunk);
  3793. // 2. Return the result of reacting to transformPromise with the following rejection steps given the argument r:
  3794. auto react_result = WebIDL::react_to_promise(*transform_promise,
  3795. {},
  3796. GC::create_function(realm.heap(), [&controller](JS::Value reason) -> WebIDL::ExceptionOr<JS::Value> {
  3797. // 1. Perform ! TransformStreamError(controller.[[stream]], r).
  3798. transform_stream_error(*controller.stream(), reason);
  3799. // 2. Throw r.
  3800. return JS::throw_completion(reason);
  3801. }));
  3802. return react_result;
  3803. }
  3804. // https://streams.spec.whatwg.org/#transform-stream-default-sink-abort-algorithm
  3805. GC::Ref<WebIDL::Promise> transform_stream_default_sink_abort_algorithm(TransformStream& stream, JS::Value reason)
  3806. {
  3807. auto& realm = stream.realm();
  3808. // 1. Let controller be stream.[[controller]].
  3809. auto controller = stream.controller();
  3810. VERIFY(controller);
  3811. // 2. If controller.[[finishPromise]] is not undefined, return controller.[[finishPromise]].
  3812. if (controller->finish_promise())
  3813. return GC::Ref { *controller->finish_promise() };
  3814. // 3. Let readable be stream.[[readable]].
  3815. auto readable = stream.readable();
  3816. // 4. Let controller.[[finishPromise]] be a new promise.
  3817. controller->set_finish_promise(WebIDL::create_promise(realm));
  3818. // 5. Let cancelPromise be the result of performing controller.[[cancelAlgorithm]], passing reason.
  3819. auto cancel_promise = controller->cancel_algorithm()->function()(reason);
  3820. // 6. Perform ! TransformStreamDefaultControllerClearAlgorithms(controller).
  3821. transform_stream_default_controller_clear_algorithms(*controller);
  3822. // 7. React to cancelPromise:
  3823. WebIDL::react_to_promise(
  3824. *cancel_promise,
  3825. // 1. If cancelPromise was fulfilled, then:
  3826. GC::create_function(realm.heap(), [&realm, readable, controller](JS::Value reason) -> WebIDL::ExceptionOr<JS::Value> {
  3827. // 1. If readable.[[state]] is "errored", reject controller.[[finishPromise]] with readable.[[storedError]].
  3828. if (readable->state() == ReadableStream::State::Errored) {
  3829. WebIDL::reject_promise(realm, *controller->finish_promise(), readable->stored_error());
  3830. }
  3831. // 2. Otherwise:
  3832. else {
  3833. VERIFY(readable->controller().has_value() && readable->controller()->has<GC::Ref<ReadableStreamDefaultController>>());
  3834. // 1. Perform ! ReadableStreamDefaultControllerError(readable.[[controller]], reason).
  3835. readable_stream_default_controller_error(readable->controller()->get<GC::Ref<ReadableStreamDefaultController>>(), reason);
  3836. // 2. Resolve controller.[[finishPromise]] with undefined.
  3837. WebIDL::resolve_promise(realm, *controller->finish_promise(), JS::js_undefined());
  3838. }
  3839. return JS::js_undefined();
  3840. }),
  3841. // 2. If cancelPromise was rejected with reason r, then:
  3842. GC::create_function(realm.heap(), [&realm, readable, controller](JS::Value reason) -> WebIDL::ExceptionOr<JS::Value> {
  3843. VERIFY(readable->controller().has_value() && readable->controller()->has<GC::Ref<ReadableStreamDefaultController>>());
  3844. // 1. Perform ! ReadableStreamDefaultControllerError(readable.[[controller]], r).
  3845. readable_stream_default_controller_error(readable->controller()->get<GC::Ref<ReadableStreamDefaultController>>(), reason);
  3846. // 2. Reject controller.[[finishPromise]] with r.
  3847. WebIDL::reject_promise(realm, *controller->finish_promise(), reason);
  3848. return JS::js_undefined();
  3849. }));
  3850. // 8. Return controller.[[finishPromise]].
  3851. return *controller->finish_promise();
  3852. }
  3853. // https://streams.spec.whatwg.org/#transform-stream-default-sink-close-algorithm
  3854. GC::Ref<WebIDL::Promise> transform_stream_default_sink_close_algorithm(TransformStream& stream)
  3855. {
  3856. auto& realm = stream.realm();
  3857. // 1. Let readable be stream.[[readable]].
  3858. auto readable = stream.readable();
  3859. // 2. Let controller be stream.[[controller]].
  3860. auto controller = stream.controller();
  3861. // 3. Let flushPromise be the result of performing controller.[[flushAlgorithm]].
  3862. auto flush_promise = controller->flush_algorithm()->function()();
  3863. // 4. Perform ! TransformStreamDefaultControllerClearAlgorithms(controller).
  3864. transform_stream_default_controller_clear_algorithms(*controller);
  3865. // 5. Return the result of reacting to flushPromise:
  3866. auto react_result = WebIDL::react_to_promise(
  3867. *flush_promise,
  3868. // 1. If flushPromise was fulfilled, then:
  3869. GC::create_function(realm.heap(), [readable](JS::Value) -> WebIDL::ExceptionOr<JS::Value> {
  3870. // 1. If readable.[[state]] is "errored", throw readable.[[storedError]].
  3871. if (readable->state() == ReadableStream::State::Errored)
  3872. return JS::throw_completion(readable->stored_error());
  3873. VERIFY(readable->controller().has_value() && readable->controller()->has<GC::Ref<ReadableStreamDefaultController>>());
  3874. // 2. Perform ! ReadableStreamDefaultControllerClose(readable.[[controller]]).
  3875. readable_stream_default_controller_close(readable->controller().value().get<GC::Ref<ReadableStreamDefaultController>>());
  3876. return JS::js_undefined();
  3877. }),
  3878. // 2. If flushPromise was rejected with reason r, then:
  3879. GC::create_function(realm.heap(), [&stream, readable](JS::Value reason) -> WebIDL::ExceptionOr<JS::Value> {
  3880. // 1. Perform ! TransformStreamError(stream, r).
  3881. transform_stream_error(stream, reason);
  3882. // 2. Throw readable.[[storedError]].
  3883. return JS::throw_completion(readable->stored_error());
  3884. }));
  3885. return react_result;
  3886. }
  3887. // https://streams.spec.whatwg.org/#transform-stream-default-sink-write-algorithm
  3888. GC::Ref<WebIDL::Promise> transform_stream_default_sink_write_algorithm(TransformStream& stream, JS::Value chunk)
  3889. {
  3890. auto& realm = stream.realm();
  3891. // 1. Assert: stream.[[writable]].[[state]] is "writable".
  3892. VERIFY(stream.writable()->state() == WritableStream::State::Writable);
  3893. // 2. Let controller be stream.[[controller]].
  3894. auto controller = stream.controller();
  3895. // 3. If stream.[[backpressure]] is true,
  3896. if (stream.backpressure().has_value() && *stream.backpressure()) {
  3897. // 1. Let backpressureChangePromise be stream.[[backpressureChangePromise]].
  3898. auto backpressure_change_promise = stream.backpressure_change_promise();
  3899. // 2. Assert: backpressureChangePromise is not undefined.
  3900. VERIFY(backpressure_change_promise);
  3901. // 3. Return the result of reacting to backpressureChangePromise with the following fulfillment steps:
  3902. auto react_result = WebIDL::react_to_promise(*backpressure_change_promise,
  3903. GC::create_function(realm.heap(), [&stream, controller, chunk](JS::Value) -> WebIDL::ExceptionOr<JS::Value> {
  3904. // 1. Let writable be stream.[[writable]].
  3905. auto writable = stream.writable();
  3906. // 2. Let state be writable.[[state]].
  3907. auto state = writable->state();
  3908. // 3. If state is "erroring", throw writable.[[storedError]].
  3909. if (state == WritableStream::State::Erroring)
  3910. return JS::throw_completion(writable->stored_error());
  3911. // 4. Assert: state is "writable".
  3912. VERIFY(state == WritableStream::State::Writable);
  3913. // 5. Return ! TransformStreamDefaultControllerPerformTransform(controller, chunk).
  3914. return transform_stream_default_controller_perform_transform(*controller, chunk)->promise();
  3915. }),
  3916. {});
  3917. return react_result;
  3918. }
  3919. // 4. Return ! TransformStreamDefaultControllerPerformTransform(controller, chunk).
  3920. return transform_stream_default_controller_perform_transform(*controller, chunk);
  3921. }
  3922. GC::Ref<WebIDL::Promise> transform_stream_default_source_pull_algorithm(TransformStream& stream)
  3923. {
  3924. // 1. Assert: stream.[[backpressure]] is true.
  3925. VERIFY(stream.backpressure().has_value() && *stream.backpressure());
  3926. // 2. Assert: stream.[[backpressureChangePromise]] is not undefined.
  3927. VERIFY(stream.backpressure_change_promise());
  3928. // 3. Perform ! TransformStreamSetBackpressure(stream, false).
  3929. transform_stream_set_backpressure(stream, false);
  3930. // 4. Return stream.[[backpressureChangePromise]].
  3931. return GC::Ref { *stream.backpressure_change_promise() };
  3932. }
  3933. // https://streams.spec.whatwg.org/#transform-stream-default-source-cancel
  3934. GC::Ref<WebIDL::Promise> transform_stream_default_source_cancel_algorithm(TransformStream& stream, JS::Value reason)
  3935. {
  3936. auto& realm = stream.realm();
  3937. // 1. Let controller be stream.[[controller]].
  3938. auto controller = stream.controller();
  3939. // 2. If controller.[[finishPromise]] is not undefined, return controller.[[finishPromise]].
  3940. if (controller->finish_promise())
  3941. return GC::Ref { *controller->finish_promise() };
  3942. // 3. Let writable be stream.[[writable]].
  3943. auto writable = stream.writable();
  3944. // 4. Let controller.[[finishPromise]] be a new promise.
  3945. controller->set_finish_promise(WebIDL::create_promise(realm));
  3946. // 5. Let cancelPromise be the result of performing controller.[[cancelAlgorithm]], passing reason.
  3947. auto cancel_promise = controller->cancel_algorithm()->function()(reason);
  3948. // 6. Perform ! TransformStreamDefaultControllerClearAlgorithms(controller).
  3949. transform_stream_default_controller_clear_algorithms(*controller);
  3950. // 7. React to cancelPromise:
  3951. WebIDL::react_to_promise(
  3952. *cancel_promise,
  3953. // 1. If cancelPromise was fulfilled, then:
  3954. GC::create_function(realm.heap(), [&realm, writable, controller, &stream, reason](JS::Value) -> WebIDL::ExceptionOr<JS::Value> {
  3955. // 1. If writable.[[state]] is "errored", reject controller.[[finishPromise]] with writable.[[storedError]].
  3956. if (writable->state() == WritableStream::State::Errored) {
  3957. WebIDL::reject_promise(realm, *controller->finish_promise(), writable->stored_error());
  3958. }
  3959. // 2. Otherwise:
  3960. else {
  3961. // 1. Perform ! WritableStreamDefaultControllerErrorIfNeeded(writable.[[controller]], reason).
  3962. writable_stream_default_controller_error_if_needed(*writable->controller(), reason);
  3963. // 2. Perform ! TransformStreamUnblockWrite(stream).
  3964. transform_stream_unblock_write(stream);
  3965. // 3. Resolve controller.[[finishPromise]] with undefined.
  3966. WebIDL::resolve_promise(realm, *controller->finish_promise(), JS::js_undefined());
  3967. }
  3968. return JS::js_undefined();
  3969. }),
  3970. // 2. If cancelPromise was rejected with reason r, then:
  3971. GC::create_function(realm.heap(), [&realm, writable, &stream, controller](JS::Value reason) -> WebIDL::ExceptionOr<JS::Value> {
  3972. // 1. Perform ! WritableStreamDefaultControllerErrorIfNeeded(writable.[[controller]], r).
  3973. writable_stream_default_controller_error_if_needed(*writable->controller(), reason);
  3974. // 2. Perform ! TransformStreamUnblockWrite(stream).
  3975. transform_stream_unblock_write(stream);
  3976. // 3. Reject controller.[[finishPromise]] with r.
  3977. WebIDL::reject_promise(realm, *controller->finish_promise(), reason);
  3978. return JS::js_undefined();
  3979. }));
  3980. // 8. Return controller.[[finishPromise]].
  3981. return *controller->finish_promise();
  3982. }
  3983. // https://streams.spec.whatwg.org/#transform-stream-error
  3984. void transform_stream_error(TransformStream& stream, JS::Value error)
  3985. {
  3986. VERIFY(stream.readable()->controller().has_value() && stream.readable()->controller()->has<GC::Ref<ReadableStreamDefaultController>>());
  3987. auto readable_controller = stream.readable()->controller()->get<GC::Ref<ReadableStreamDefaultController>>();
  3988. // 1. Perform ! ReadableStreamDefaultControllerError(stream.[[readable]].[[controller]], e).
  3989. readable_stream_default_controller_error(*readable_controller, error);
  3990. // 2. Perform ! TransformStreamErrorWritableAndUnblockWrite(stream, e).
  3991. transform_stream_error_writable_and_unblock_write(stream, error);
  3992. }
  3993. // https://streams.spec.whatwg.org/#transform-stream-error-writable-and-unblock-write
  3994. void transform_stream_error_writable_and_unblock_write(TransformStream& stream, JS::Value error)
  3995. {
  3996. // 1. Perform ! TransformStreamDefaultControllerClearAlgorithms(stream.[[controller]]).
  3997. transform_stream_default_controller_clear_algorithms(*stream.controller());
  3998. // 2. Perform ! WritableStreamDefaultControllerErrorIfNeeded(stream.[[writable]].[[controller]], e).
  3999. writable_stream_default_controller_error_if_needed(*stream.writable()->controller(), error);
  4000. // 3. Perform ! TransformStreamUnblockWrite(stream).
  4001. transform_stream_unblock_write(stream);
  4002. }
  4003. // https://streams.spec.whatwg.org/#transform-stream-set-backpressure
  4004. void transform_stream_set_backpressure(TransformStream& stream, bool backpressure)
  4005. {
  4006. auto& realm = stream.realm();
  4007. // 1. Assert: stream.[[backpressure]] is not backpressure.
  4008. VERIFY(stream.backpressure() != backpressure);
  4009. // 2. If stream.[[backpressureChangePromise]] is not undefined, resolve stream.[[backpressureChangePromise]] with undefined.
  4010. if (stream.backpressure_change_promise())
  4011. WebIDL::resolve_promise(realm, *stream.backpressure_change_promise(), JS::js_undefined());
  4012. // 3. Set stream.[[backpressureChangePromise]] to a new promise.
  4013. stream.set_backpressure_change_promise(WebIDL::create_promise(realm));
  4014. // 4. Set stream.[[backpressure]] to backpressure.
  4015. stream.set_backpressure(backpressure);
  4016. }
  4017. // https://streams.spec.whatwg.org/#transform-stream-unblock-write
  4018. void transform_stream_unblock_write(TransformStream& stream)
  4019. {
  4020. // 1. If stream.[[backpressure]] is true, perform ! TransformStreamSetBackpressure(stream, false).
  4021. if (stream.backpressure().has_value() && stream.backpressure().value())
  4022. transform_stream_set_backpressure(stream, false);
  4023. }
  4024. // https://streams.spec.whatwg.org/#is-non-negative-number
  4025. bool is_non_negative_number(JS::Value value)
  4026. {
  4027. // 1. If v is not a Number, return false.
  4028. if (!value.is_number())
  4029. return false;
  4030. // 2. If v is NaN, return false.
  4031. if (value.is_nan())
  4032. return false;
  4033. // 3. If v < 0, return false.
  4034. if (value.as_double() < 0.0)
  4035. return false;
  4036. // 4. Return true.
  4037. return true;
  4038. }
  4039. // https://streams.spec.whatwg.org/#abstract-opdef-cancopydatablockbytes
  4040. bool can_copy_data_block_bytes_buffer(JS::ArrayBuffer const& to_buffer, u64 to_index, JS::ArrayBuffer const& from_buffer, u64 from_index, u64 count)
  4041. {
  4042. // 1. Assert: toBuffer is an Object.
  4043. // 2. Assert: toBuffer has an [[ArrayBufferData]] internal slot.
  4044. // 3. Assert: fromBuffer is an Object.
  4045. // 4. Assert: fromBuffer has an [[ArrayBufferData]] internal slot.
  4046. // 5. If toBuffer is fromBuffer, return false.
  4047. if (&to_buffer == &from_buffer)
  4048. return false;
  4049. // 6. If ! IsDetachedBuffer(toBuffer) is true, return false.
  4050. if (to_buffer.is_detached())
  4051. return false;
  4052. // 7. If ! IsDetachedBuffer(fromBuffer) is true, return false.
  4053. if (from_buffer.is_detached())
  4054. return false;
  4055. // 8. If toIndex + count > toBuffer.[[ArrayBufferByteLength]], return false.
  4056. if (to_index + count > to_buffer.byte_length())
  4057. return false;
  4058. // 9. If fromIndex + count > fromBuffer.[[ArrayBufferByteLength]], return false.
  4059. if (from_index + count > from_buffer.byte_length())
  4060. return false;
  4061. // 10. Return true.
  4062. return true;
  4063. }
  4064. // https://streams.spec.whatwg.org/#can-transfer-array-buffer
  4065. bool can_transfer_array_buffer(JS::ArrayBuffer const& array_buffer)
  4066. {
  4067. // 1. Assert: O is an Object.
  4068. // 2. Assert: O has an [[ArrayBufferData]] internal slot.
  4069. // 3. If ! IsDetachedBuffer(O) is true, return false.
  4070. if (array_buffer.is_detached())
  4071. return false;
  4072. // 4. If SameValue(O.[[ArrayBufferDetachKey]], undefined) is false, return false.
  4073. if (!JS::same_value(array_buffer.detach_key(), JS::js_undefined()))
  4074. return false;
  4075. // 5. Return true.
  4076. return true;
  4077. }
  4078. // https://streams.spec.whatwg.org/#abstract-opdef-cloneasuint8array
  4079. WebIDL::ExceptionOr<JS::Value> clone_as_uint8_array(JS::Realm& realm, WebIDL::ArrayBufferView& view)
  4080. {
  4081. auto& vm = realm.vm();
  4082. // 1. Assert: O is an Object.
  4083. // 2. Assert: O has an [[ViewedArrayBuffer]] internal slot.
  4084. // 3. Assert: ! IsDetachedBuffer(O.[[ViewedArrayBuffer]]) is false.
  4085. VERIFY(!view.viewed_array_buffer()->is_detached());
  4086. // 4. Let buffer be ? CloneArrayBuffer(O.[[ViewedArrayBuffer]], O.[[ByteOffset]], O.[[ByteLength]], %ArrayBuffer%).
  4087. auto* buffer = TRY(JS::clone_array_buffer(vm, *view.viewed_array_buffer(), view.byte_offset(), view.byte_length()));
  4088. // 5. Let array be ! Construct(%Uint8Array%, « buffer »).
  4089. auto array = MUST(JS::construct(vm, *realm.intrinsics().uint8_array_constructor(), buffer));
  4090. // 5. Return array.
  4091. return array;
  4092. }
  4093. // https://streams.spec.whatwg.org/#abstract-opdef-structuredclone
  4094. WebIDL::ExceptionOr<JS::Value> structured_clone(JS::Realm& realm, JS::Value value)
  4095. {
  4096. auto& vm = realm.vm();
  4097. // 1. Let serialized be ? StructuredSerialize(v).
  4098. auto serialized = TRY(HTML::structured_serialize(vm, value));
  4099. // 2. Return ? StructuredDeserialize(serialized, the current Realm).
  4100. return TRY(HTML::structured_deserialize(vm, serialized, realm));
  4101. }
  4102. // Non-standard function to aid in converting a user-provided function into a WebIDL::Callback. This is essentially
  4103. // what the Bindings generator would do at compile time, but at runtime instead.
  4104. JS::ThrowCompletionOr<GC::Root<WebIDL::CallbackType>> property_to_callback(JS::VM& vm, JS::Value value, JS::PropertyKey const& property_key, WebIDL::OperationReturnsPromise operation_returns_promise)
  4105. {
  4106. auto property = TRY(value.get(vm, property_key));
  4107. if (property.is_undefined())
  4108. return GC::Root<WebIDL::CallbackType> {};
  4109. if (!property.is_function())
  4110. return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAFunction, property.to_string_without_side_effects());
  4111. return vm.heap().allocate<WebIDL::CallbackType>(property.as_object(), HTML::incumbent_realm(), operation_returns_promise);
  4112. }
  4113. // https://streams.spec.whatwg.org/#set-up-readable-byte-stream-controller-from-underlying-source
  4114. WebIDL::ExceptionOr<void> set_up_readable_byte_stream_controller_from_underlying_source(ReadableStream& stream, JS::Value underlying_source, UnderlyingSource const& underlying_source_dict, double high_water_mark)
  4115. {
  4116. auto& realm = stream.realm();
  4117. // 1. Let controller be a new ReadableByteStreamController.
  4118. auto controller = realm.create<ReadableByteStreamController>(realm);
  4119. // 2. Let startAlgorithm be an algorithm that returns undefined.
  4120. auto start_algorithm = GC::create_function(realm.heap(), []() -> WebIDL::ExceptionOr<JS::Value> { return JS::js_undefined(); });
  4121. // 3. Let pullAlgorithm be an algorithm that returns a promise resolved with undefined.
  4122. auto pull_algorithm = GC::create_function(realm.heap(), [&realm]() {
  4123. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  4124. });
  4125. // 4. Let cancelAlgorithm be an algorithm that returns a promise resolved with undefined.
  4126. auto cancel_algorithm = GC::create_function(realm.heap(), [&realm](JS::Value) {
  4127. return WebIDL::create_resolved_promise(realm, JS::js_undefined());
  4128. });
  4129. // 5. If underlyingSourceDict["start"] exists, then set startAlgorithm to an algorithm which returns the result of invoking underlyingSourceDict["start"] with argument list « controller » and callback this value underlyingSource.
  4130. if (underlying_source_dict.start) {
  4131. start_algorithm = GC::create_function(realm.heap(), [controller, underlying_source, callback = underlying_source_dict.start]() -> WebIDL::ExceptionOr<JS::Value> {
  4132. // Note: callback does not return a promise, so invoke_callback may return an abrupt completion
  4133. return TRY(WebIDL::invoke_callback(*callback, underlying_source, controller)).release_value();
  4134. });
  4135. }
  4136. // 6. If underlyingSourceDict["pull"] exists, then set pullAlgorithm to an algorithm which returns the result of invoking underlyingSourceDict["pull"] with argument list « controller » and callback this value underlyingSource.
  4137. if (underlying_source_dict.pull) {
  4138. pull_algorithm = GC::create_function(realm.heap(), [&realm, controller, underlying_source, callback = underlying_source_dict.pull]() {
  4139. // Note: callback returns a promise, so invoke_callback will never return an abrupt completion
  4140. auto result = MUST(WebIDL::invoke_callback(*callback, underlying_source, controller)).release_value();
  4141. return WebIDL::create_resolved_promise(realm, result);
  4142. });
  4143. }
  4144. // 7. If underlyingSourceDict["cancel"] exists, then set cancelAlgorithm to an algorithm which takes an argument reason and returns the result of invoking underlyingSourceDict["cancel"] with argument list « reason » and callback this value underlyingSource.
  4145. if (underlying_source_dict.cancel) {
  4146. cancel_algorithm = GC::create_function(realm.heap(), [&realm, underlying_source, callback = underlying_source_dict.cancel](JS::Value reason) {
  4147. // Note: callback returns a promise, so invoke_callback will never return an abrupt completion
  4148. auto result = MUST(WebIDL::invoke_callback(*callback, underlying_source, reason)).release_value();
  4149. return WebIDL::create_resolved_promise(realm, result);
  4150. });
  4151. }
  4152. // 8. Let autoAllocateChunkSize be underlyingSourceDict["autoAllocateChunkSize"], if it exists, or undefined otherwise.
  4153. auto auto_allocate_chunk_size = underlying_source_dict.auto_allocate_chunk_size.has_value()
  4154. ? JS::Value(underlying_source_dict.auto_allocate_chunk_size.value())
  4155. : JS::js_undefined();
  4156. // 9. If autoAllocateChunkSize is 0, then throw a TypeError exception.
  4157. if (auto_allocate_chunk_size.is_integral_number() && auto_allocate_chunk_size.as_double() == 0)
  4158. return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Cannot use an auto allocate chunk size of 0"sv };
  4159. // 10. Perform ? SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize).
  4160. return set_up_readable_byte_stream_controller(stream, controller, start_algorithm, pull_algorithm, cancel_algorithm, high_water_mark, auto_allocate_chunk_size);
  4161. }
  4162. }