char/avril
(wip) why'd you have to go and make things so complicaaaaated?
git clone https://git.t4t.associates/char/avril
44fe2c6
main
1import { 2Array , 3ArrayPrototypePush as push , 4Error , 5ErrorGetStack , 6Map , 7MapPrototypeDelete as mapDelete , 8MapPrototypeGet as mapGet , 9MapPrototypeSet as mapSet , 10NumberIsFinite as isFinite , 11ObjectCreate , 12ObjectDefineProperty as define , 13ObjectSetPrototypeOf , 14ReflectApply as apply , 15ReflectConstruct as construct , 16TypeError , 17uncurryThis , 18WeakMap , 19WeakMapPrototypeGet as get , 20WeakMapPrototypeSet as set , 21} from "ext:core/primordials" ; 22import { 23array , 24dictionary , 25required , 26state , 27string , 28usv , 29} from "ext:web/idl.js" ; 30import { op_timer_now as now } from "ext:core/ops" ; 31import { enqueueMicrotask } from "ext:core/microtasks" ; 32import { isPromise } from "ext:core/event_hooks" ; 33import { scheduleTimeout } from "ext:timers/timers.js" ; 34import { 35registerSerializable , 36registerUncloneable , 37registerWire , 38} from "./serialization.js" ; 39 40interface EventState { 41type :string ; 42bubbles :boolean ; 43cancelable :boolean ; 44composed :boolean ; 45target :EventTarget | null ; 46phase :number ; 47dispatching :boolean ; 48stopped :boolean ; 49immediate :boolean ; 50prevented :boolean ; 51passive :boolean ; 52trusted :boolean ; 53time :number ; 54} 55interface ExceptionState { 56message :string ; 57name :string ; 58} 59interface Listener { 60type :string ; 61callback :EventListener ; 62capture :boolean ; 63once :boolean ; 64passive :boolean ; 65active :boolean ; 66} 67export type EventListener = (( this :EventTarget , event :Event ) => unknown ) | { 68handleEvent ( event :Event ) :unknown ; 69}; 70interface SignalState { 71aborted :boolean ; 72reason :unknown ; 73algorithms :(() => void )[]; 74handler :(( event :Event ) => unknown ) | null ; 75handlerListener ?:(( event :Event ) => void ) | null ; 76} 77const events = new WeakMap < object , EventState >(), 78customEvents = new WeakMap < object , { detail :unknown }>(), 79errorEvents = new WeakMap < 80object , 81{ 82message :string ; 83filename :string ; 84lineno :number ; 85colno :number ; 86error :unknown ; 87} 88>(), 89rejectionEvents = new WeakMap < 90object , 91{ promise :Promise < unknown >; reason :unknown } 92>(), 93targets = new WeakMap < object , Listener []>(), 94listenerObservers = new WeakMap < object , ( target :object ) => void >(), 95signals = new WeakMap < object , SignalState >(), 96controllers = new WeakMap < object , AbortSignal >(), 97exceptions = new WeakMap < object , ExceptionState >(); 98registerUncloneable ( events ); 99registerUncloneable ( customEvents ); 100registerUncloneable ( errorEvents ); 101registerUncloneable ( rejectionEvents ); 102registerUncloneable ( targets ); 103registerUncloneable ( signals ); 104registerUncloneable ( controllers ); 105const secret = ObjectCreate ( null ), trunc = Math . trunc , floor = Math . floor ; 106function trustedGetter ( this :object ) :boolean { 107return state ( events , this ). trusted ; 108} 109const WeakRef = globalThis . WeakRef , 110deref = uncurryThis ( WeakRef . prototype . deref ); 111const slice :< T > ( array :readonly T [], start ?:number , end ?:number ) => T [] = 112uncurryThis ( Array . prototype . slice ); 113let globalTarget :object | undefined , reporting = false ; 114const pendingReports = new Map < unknown , number >(); 115function report ( error :unknown ) :void { 116reportErrorValue ( error ); 117} 118class DOMException extends Error { 119// @ts-expect-error Reflect.construct preserves the native Error prototype without a guest-replaceable super(). 120constructor ( message :unknown = "" , name :unknown = "Error" ) { 121const convertedMessage = string ( message ), convertedName = string ( name ); 122const self = construct ( Error , [ convertedMessage ], new . target ) as { 123message ?:unknown ; 124}; 125delete self . message ; 126set ( exceptions , self , { message :convertedMessage , name :convertedName }); 127return self as DOMException ; 128} 129get name () { 130return state ( exceptions , this ). name ; 131} 132get message () { 133return state ( exceptions , this ). message ; 134} 135get code () { 136switch ( state ( exceptions , this ). name ) { 137case "IndexSizeError" : 138return 1 ; 139case "HierarchyRequestError" : 140return 3 ; 141case "WrongDocumentError" : 142return 4 ; 143case "InvalidCharacterError" : 144return 5 ; 145case "NoModificationAllowedError" : 146return 7 ; 147case "NotFoundError" : 148return 8 ; 149case "NotSupportedError" : 150return 9 ; 151case "InUseAttributeError" : 152return 10 ; 153case "InvalidStateError" : 154return 11 ; 155case "SyntaxError" : 156return 12 ; 157case "InvalidModificationError" : 158return 13 ; 159case "NamespaceError" : 160return 14 ; 161case "InvalidAccessError" : 162return 15 ; 163case "TypeMismatchError" : 164return 17 ; 165case "SecurityError" : 166return 18 ; 167case "NetworkError" : 168return 19 ; 169case "AbortError" : 170return 20 ; 171case "URLMismatchError" : 172return 21 ; 173case "QuotaExceededError" : 174return 22 ; 175case "TimeoutError" : 176return 23 ; 177case "InvalidNodeTypeError" : 178return 24 ; 179case "DataCloneError" : 180return 25 ; 181default : 182return 0 ; 183} 184} 185} 186for ( 187const [ name , value ] of [ 188[ "INDEX_SIZE_ERR" , 1 ], 189[ "DOMSTRING_SIZE_ERR" , 2 ], 190[ "HIERARCHY_REQUEST_ERR" , 3 ], 191[ "WRONG_DOCUMENT_ERR" , 4 ], 192[ "INVALID_CHARACTER_ERR" , 5 ], 193[ "NO_DATA_ALLOWED_ERR" , 6 ], 194[ "NO_MODIFICATION_ALLOWED_ERR" , 7 ], 195[ "NOT_FOUND_ERR" , 8 ], 196[ "NOT_SUPPORTED_ERR" , 9 ], 197[ "INUSE_ATTRIBUTE_ERR" , 10 ], 198[ "INVALID_STATE_ERR" , 11 ], 199[ "SYNTAX_ERR" , 12 ], 200[ "INVALID_MODIFICATION_ERR" , 13 ], 201[ "NAMESPACE_ERR" , 14 ], 202[ "INVALID_ACCESS_ERR" , 15 ], 203[ "VALIDATION_ERR" , 16 ], 204[ "TYPE_MISMATCH_ERR" , 17 ], 205[ "SECURITY_ERR" , 18 ], 206[ "NETWORK_ERR" , 19 ], 207[ "ABORT_ERR" , 20 ], 208[ "URL_MISMATCH_ERR" , 21 ], 209[ "QUOTA_EXCEEDED_ERR" , 22 ], 210[ "TIMEOUT_ERR" , 23 ], 211[ "INVALID_NODE_TYPE_ERR" , 24 ], 212[ "DATA_CLONE_ERR" , 25 ], 213] 214) { 215define ( DOMException , name , { value, enumerable :true }); 216define ( DOMException . prototype , name , { value, enumerable :true }); 217} 218function createException ( 219data :ExceptionState , 220stack :unknown = undefined , 221) :DOMException { 222// Construct native Error data without a guest-replaceable dynamic super() call. 223const result = construct ( Error , [ data . message ], DOMException ) as { 224message ?:unknown ; 225}; 226delete result . message ; 227if ( typeof stack === "string" ) { 228define ( result , "stack" , { 229value :stack , 230writable :true , 231configurable :true , 232}); 233} 234set ( exceptions , result , data ); 235return result as DOMException ; 236} 237function dataCloneError ( message :string ) :DOMException { 238return createException ({ message, name :"DataCloneError" }); 239} 240registerSerializable ( 241exceptions , 242( data :ExceptionState , source :object ) => 243createException ( data , ErrorGetStack ( source )), 244); 245registerWire ({ 246name :"DOMException" , 247states :exceptions , 248encode :( data ) => data , 249decode :( data :unknown ) => createException ( data as ExceptionState ), 250}); 251class Event { 252constructor ( type :unknown , init :unknown = {}) { 253if ( arguments . length === 0 ) throw new TypeError ( "Event requires a type" ); 254type = string ( type ); 255const options = dictionary ( init ); 256set ( events , this , { 257type :type as string , 258bubbles :!! options . bubbles , 259cancelable :!! options . cancelable , 260composed :!! options . composed , 261target :null , 262phase :0 , 263dispatching :false , 264stopped :false , 265immediate :false , 266prevented :false , 267passive :false , 268trusted :false , 269time :floor ( now ( null ) * 10 ) / 10 , 270}); 271define ( this , "isTrusted" , { 272get :trustedGetter , 273enumerable :true , 274}); 275} 276get type () { 277return state ( events , this ). type ; 278} 279get bubbles () { 280return state ( events , this ). bubbles ; 281} 282get cancelable () { 283return state ( events , this ). cancelable ; 284} 285get composed () { 286return state ( events , this ). composed ; 287} 288get target () { 289return state ( events , this ). target ; 290} 291get srcElement () { 292return state ( events , this ). target ; 293} 294get currentTarget () { 295const s = state ( events , this ); 296return s . dispatching ?s . target :null ; 297} 298get eventPhase () { 299return state ( events , this ). phase ; 300} 301get timeStamp () { 302return state ( events , this ). time ; 303} 304get defaultPrevented () { 305return state ( events , this ). prevented ; 306} 307get cancelBubble () { 308return state ( events , this ). stopped ; 309} 310set cancelBubble ( value ) { 311if ( value ) state ( events , this ). stopped = true ; 312} 313get returnValue () { 314return ! state ( events , this ). prevented ; 315} 316set returnValue ( value ) { 317const s = state ( events , this ); 318if ( ! value && s . cancelable && ! s . passive ) s . prevented = true ; 319} 320preventDefault () { 321const s = state ( events , this ); 322if ( s . cancelable && ! s . passive ) s . prevented = true ; 323} 324stopPropagation () { 325state ( events , this ). stopped = true ; 326} 327stopImmediatePropagation () { 328const s = state ( events , this ); 329s . stopped = s . immediate = true ; 330} 331composedPath () { 332const s = state ( events , this ); 333return s . dispatching ?[ s . target ] :[]; 334} 335initEvent ( 336type :unknown , 337bubbles :unknown = false , 338cancelable :unknown = false , 339) { 340required ( arguments . length , 1 ); 341type = string ( type ); 342bubbles = !! bubbles ; 343cancelable = !! cancelable ; 344const s = state ( events , this ); 345if ( s . dispatching ) return ; 346s . type = type as string ; 347s . bubbles = bubbles as boolean ; 348s . cancelable = cancelable as boolean ; 349s . composed = false ; 350s . target = null ; 351s . phase = 0 ; 352s . trusted = false ; 353s . stopped = s . immediate = s . prevented = false ; 354} 355} 356for ( 357const [ name , value ] of [ 358[ "NONE" , 0 ], 359[ "CAPTURING_PHASE" , 1 ], 360[ "AT_TARGET" , 2 ], 361[ "BUBBLING_PHASE" , 3 ], 362] 363) { 364define ( Event , name , { value, enumerable :true }); 365define ( Event . prototype , name , { value, enumerable :true }); 366} 367class CustomEvent extends Event { 368// @ts-expect-error Reflect.construct preserves new.target without a guest-replaceable super(). 369constructor ( type :unknown , init :unknown = {}) { 370required ( arguments . length , 1 ); 371type = string ( type ); 372const options = dictionary ( init ); 373const self = construct ( Event , [ type , options ], new . target ); 374const detail = options . detail ; 375set ( customEvents , self , { 376detail :detail === undefined ?null :detail , 377}); 378return self as CustomEvent ; 379} 380get detail () { 381return state ( customEvents , this ). detail ; 382} 383} 384class ErrorEvent extends Event { 385// @ts-expect-error Reflect.construct preserves new.target without a guest-replaceable super(). 386constructor ( type :unknown , init :unknown = {}) { 387required ( arguments . length , 1 ); 388type = string ( type ); 389const options = dictionary ( init ); 390const self = construct ( Event , [ type , options ], new . target ); 391const message = options . message , 392filename = options . filename , 393error = options . error , 394lineno = options . lineno , 395colno = options . colno ; 396set ( errorEvents , self , { 397message :message === undefined ?"" :string ( message ), 398filename :filename === undefined ?"" :string ( filename ), 399lineno :lineno === undefined ?0 :+ ( lineno as number ) >>> 0 , 400colno :colno === undefined ?0 :+ ( colno as number ) >>> 0 , 401error :error === undefined ?null :error , 402}); 403return self as ErrorEvent ; 404} 405get message () { 406return state ( errorEvents , this ). message ; 407} 408get filename () { 409return state ( errorEvents , this ). filename ; 410} 411get lineno () { 412return state ( errorEvents , this ). lineno ; 413} 414get colno () { 415return state ( errorEvents , this ). colno ; 416} 417get error () { 418return state ( errorEvents , this ). error ; 419} 420} 421class PromiseRejectionEvent extends Event { 422// @ts-expect-error Reflect.construct preserves new.target without a guest-replaceable super(). 423constructor ( type :unknown , init :unknown = {}) { 424required ( arguments . length , 1 ); 425type = string ( type ); 426const options = dictionary ( init ); 427const self = construct ( Event , [ type , options ], new . target ); 428const promise = options . promise ; 429if ( ! isPromise ( promise )) { 430throw new TypeError ( "Expected a Promise" ); 431} 432set ( rejectionEvents , self , { 433 promise, 434reason :options . reason , 435}); 436return self as PromiseRejectionEvent ; 437} 438get promise () { 439return state ( rejectionEvents , this ). promise ; 440} 441get reason () { 442return state ( rejectionEvents , this ). reason ; 443} 444} 445function dispatchEvent ( 446target :object , 447event :Event , 448trusted :boolean , 449) :boolean { 450const list = state ( targets , target ), s = state ( events , event ); 451if ( s . dispatching || ! s . type ) { 452throw new DOMException ( 453"Event is already dispatching or uninitialized" , 454"InvalidStateError" , 455); 456} 457s . trusted = trusted ; 458s . dispatching = true ; 459s . target = target as EventTarget ; 460s . phase = 2 ; 461s . stopped = s . immediate = false ; 462const snapshot = slice ( list ); 463for ( let i = 0 ; i < snapshot . length ; i ++ ) { 464const l = snapshot [ i ]; 465if ( ! l . active || l . type !== s . type ) continue ; 466if ( l . once ) { 467l . active = false ; 468listenersChanged ( target ); 469} 470s . passive = l . passive ; 471try { 472if ( typeof l . callback === "function" ) { 473apply ( l . callback , target , [ event ]); 474} else l . callback . handleEvent ( event ); 475} catch ( error ) { 476report ( error ); 477} 478if ( s . immediate ) break ; 479} 480s . passive = false ; 481s . dispatching = false ; 482s . phase = 0 ; 483return ! s . prevented ; 484} 485class EventTarget { 486constructor () { 487set ( targets , this , array ()); 488} 489addEventListener ( 490type :unknown , 491callback :EventListener | null | undefined , 492options ?:unknown , 493) :void ; 494addEventListener ( 495type :unknown , 496callback :unknown , 497options :unknown = {}, 498) :void { 499required ( arguments . length , 2 ); 500const list = state ( targets , this ); 501type = string ( type ); 502if ( callback === null || callback === undefined ) return ; 503if ( typeof callback !== "function" && typeof callback !== "object" ) { 504throw new TypeError ( "Invalid event listener" ); 505} 506const capture = typeof options === "boolean" 507 ?options 508 :!! ( options as Record < PropertyKey , unknown > | null | undefined )?. capture ; 509for ( let i = 0 ; i < list . length ; i ++ ) { 510if ( 511list [ i ]. active && list [ i ]. type === type && 512list [ i ]. callback === callback && list [ i ]. capture === capture 513) return ; 514} 515const signal = typeof options === "object" 516 ?( options as Record < PropertyKey , unknown > | null )?. signal as 517| AbortSignal 518| undefined 519 :undefined ; 520if ( signal !== undefined && state ( signals , signal ). aborted ) return ; 521const listener = { 522type :type as string , 523callback :callback as EventListener , 524 capture, 525once :!! ( options as Record < PropertyKey , unknown > | null | undefined ) 526?. once , 527passive :!! ( options as Record < PropertyKey , unknown > | null | undefined ) 528?. passive , 529active :true , 530}; 531push ( list , listener ); 532if ( signal !== undefined ) { 533const weakTarget = new WeakRef ( this ), 534weakListener = new WeakRef ( listener ); 535addAbort ( signal , () => { 536const current = deref ( weakListener ), target = deref ( weakTarget ); 537if ( current ) current . active = false ; 538if ( target ) listenersChanged ( target ); 539}); 540} 541listenersChanged ( this ); 542} 543removeEventListener ( 544type :unknown , 545callback :EventListener | null | undefined , 546options ?:unknown , 547) :void ; 548removeEventListener ( 549type :unknown , 550callback :unknown , 551options :unknown = {}, 552) :void { 553required ( arguments . length , 2 ); 554const list = state ( targets , this ); 555type = string ( type ); 556const capture = typeof options === "boolean" 557 ?options 558 :!! ( options as Record < PropertyKey , unknown > | null | undefined )?. capture ; 559for ( let i = 0 ; i < list . length ; i ++ ) { 560if ( 561list [ i ]. type === type && list [ i ]. callback === callback && 562list [ i ]. capture === capture 563) list [ i ]. active = false ; 564} 565listenersChanged ( this ); 566} 567dispatchEvent ( event :Event ) :boolean { 568required ( arguments . length , 1 ); 569return dispatchEvent ( this , event , false ); 570} 571} 572type CapturedListenerMethod = ( 573target :unknown , 574type :unknown , 575callback :EventListener | null | undefined , 576options ?:unknown , 577) => void ; 578const addListener = uncurryThis ( 579EventTarget . prototype . addEventListener , 580) as CapturedListenerMethod , 581removeListener = uncurryThis ( 582EventTarget . prototype . removeEventListener , 583) as CapturedListenerMethod ; 584const dispatch = ( target :unknown , event :Event ) :boolean => 585dispatchEvent ( target as object , event , true ); 586function listenersChanged ( target :object ) :void { 587const list = state ( targets , target ); 588let kept = 0 ; 589for ( let i = 0 ; i < list . length ; i ++ ) { 590if ( list [ i ]. active ) list [ kept ++ ] = list [ i ]; 591} 592list . length = kept ; 593const observer = get ( listenerObservers , target ); 594if ( observer ) observer ( target ); 595} 596function observeListeners ( 597target :object , 598observer :( target :object ) => void , 599) :void { 600state ( targets , target ); 601set ( listenerObservers , target , observer ); 602observer ( target ); 603} 604function hasListener ( target :object , type :string ) :boolean { 605const list = state ( targets , target ); 606for ( let i = 0 ; i < list . length ; i ++ ) { 607if ( list [ i ]. active && list [ i ]. type === type ) return true ; 608} 609return false ; 610} 611const isDispatching = ( event :Event ) :boolean => 612state ( events , event ). dispatching ; 613const preventDefault = uncurryThis ( Event . prototype . preventDefault ); 614const globalHandlers = ObjectCreate ( null ) as Record < string , Function | null >, 615globalListeners = ObjectCreate ( null ) as Record < string , EventListener | null >; 616function installGlobalEventTarget ( target :object ) :void { 617globalTarget = target ; 618ObjectSetPrototypeOf ( target , EventTarget . prototype ); 619set ( targets , target , array ()); 620const methods :Record < string , ( ...args :never []) => unknown > = { 621addEventListener ( 622type :unknown , 623callback :unknown , 624options :unknown = undefined , 625) { 626required ( arguments . length , 2 ); 627return addListener ( 628this ?? target , 629type , 630callback as EventListener | null , 631options , 632); 633}, 634removeEventListener ( 635type :unknown , 636callback :unknown , 637options :unknown = undefined , 638) { 639required ( arguments . length , 2 ); 640return removeListener ( 641this ?? target , 642type , 643callback as EventListener | null , 644options , 645); 646}, 647dispatchEvent ( event :Event ) { 648required ( arguments . length , 1 ); 649return dispatchEvent ( this ?? target , event , false ); 650}, 651}; 652for ( 653const name of [ "addEventListener" , "removeEventListener" , "dispatchEvent" ] 654) { 655define ( target , name , { 656value :methods [ name ], 657writable :true , 658enumerable :true , 659configurable :true , 660}); 661} 662for ( 663const [ name , type ] of [ 664[ "onerror" , "error" ], 665[ "onunhandledrejection" , "unhandledrejection" ], 666[ "onrejectionhandled" , "rejectionhandled" ], 667] 668) { 669define ( target , name , { 670get :() => globalHandlers [ name ] ?? null , 671set :( handler ) => setGlobalHandler ( name , type , handler ), 672enumerable :true , 673configurable :true , 674}); 675} 676} 677function setGlobalHandler ( name :string , type :string , handler :unknown ) :void { 678handler = typeof handler === "function" ?handler :null ; 679if ( ! handler ) { 680const listener = globalListeners [ name ]; 681if ( listener ) removeListener ( globalTarget ! , type , listener ); 682delete globalHandlers [ name ]; 683delete globalListeners [ name ]; 684return ; 685} 686globalHandlers [ name ] = handler as Function ; 687if ( globalListeners [ name ]) return ; 688const listener = ( event :Event ) => { 689const handler = globalHandlers [ name ]; 690if ( ! handler ) return ; 691const result = type === "error" 692 ?apply ( handler as ( ...args :never []) => unknown , globalTarget ! , [ 693( event as ErrorEvent ). message , 694( event as ErrorEvent ). filename , 695( event as ErrorEvent ). lineno , 696( event as ErrorEvent ). colno , 697( event as ErrorEvent ). error , 698]) 699 :apply ( handler as ( ...args :never []) => unknown , globalTarget ! , [ event ]); 700if ( type === "error" ?result === true :result === false ) { 701const s = state ( events , event ); 702if ( s . cancelable && ! s . passive ) s . prevented = true ; 703} 704}; 705globalListeners [ name ] = listener ; 706addListener ( globalTarget ! , type , listener ); 707} 708function exceptionMessage ( error :unknown ) :string { 709if ( 710error !== null && ( typeof error === "object" || typeof error === "function" ) 711) { 712try { 713const message = ( error as Record < PropertyKey , unknown >). message ; 714if ( message !== undefined ) return usv ( message ); 715} catch ( error ) { 716void error ; 717} 718} 719try { 720return usv ( error ); 721} catch { 722return "" ; 723} 724} 725function dispatchError ( 726error :unknown , 727filename = "" , 728lineno = 0 , 729colno = 0 , 730) :boolean { 731if ( reporting || ! globalTarget ) return false ; 732reporting = true ; 733try { 734const event = new ErrorEvent ( "error" , { 735cancelable :true , 736message :exceptionMessage ( error ), 737 filename, 738 lineno, 739 colno, 740 error, 741}); 742state ( errorEvents , event ). error = error ; 743dispatch ( globalTarget , event ); 744return state ( events , event ). prevented ; 745} catch { 746return false ; 747} finally { 748reporting = false ; 749} 750} 751function reportException ( 752error :unknown , 753filename = "" , 754lineno = 0 , 755colno = 0 , 756) :boolean { 757const count = mapGet ( pendingReports , error ); 758if ( count !== undefined ) { 759if ( count === 1 ) mapDelete ( pendingReports , error ); 760else mapSet ( pendingReports , error , count - 1 ); 761return false ; 762} 763return dispatchError ( error , filename , lineno , colno ); 764} 765function reportErrorValue ( error :unknown ) :void { 766if ( ! reporting && dispatchError ( error )) return ; 767mapSet ( pendingReports , error , ( mapGet ( pendingReports , error ) ?? 0 ) + 1 ); 768enqueueMicrotask (() => { 769throw error ; 770}); 771} 772function reportUnhandledRejection ( 773promise :Promise < unknown >, 774reason :unknown , 775) :boolean { 776const event = new PromiseRejectionEvent ( "unhandledrejection" , { 777cancelable :true , 778 promise, 779 reason, 780}); 781dispatch ( globalTarget ! , event ); 782return state ( events , event ). prevented ; 783} 784function reportRejectionHandled ( 785promise :Promise < unknown >, 786reason :unknown , 787) :void { 788dispatch ( 789globalTarget ! , 790new PromiseRejectionEvent ( "rejectionhandled" , { promise, reason}), 791); 792} 793function addAbort ( signal :unknown , callback :() => void ) :() => void { 794push ( state ( signals , signal ). algorithms , callback ); 795return () => { 796const current = state ( signals , signal ), 797algorithms = current . algorithms , 798remaining = array <() => void >(); 799for ( let i = 0 ; i < algorithms . length ; i ++ ) { 800if ( algorithms [ i ] !== callback ) push ( remaining , algorithms [ i ]); 801} 802current . algorithms = remaining ; 803}; 804} 805function abort ( signal :unknown , reason ?:unknown ) :void { 806const s = state ( signals , signal ); 807if ( s . aborted ) return ; 808s . aborted = true ; 809s . reason = reason === undefined 810 ?new DOMException ( "The operation was aborted" , "AbortError" ) 811 :reason ; 812const algorithms = s . algorithms ; 813s . algorithms = array <() => void >(); 814for ( let i = 0 ; i < algorithms . length ; i ++ ) algorithms [ i ](); 815dispatch ( signal , new Event ( "abort" )); 816} 817class AbortSignal extends EventTarget { 818// @ts-expect-error Reflect.construct preserves new.target without a guest-replaceable super(). 819constructor ( key :unknown ) { 820if ( key !== secret ) throw new TypeError ( "Illegal constructor" ); 821const self = construct ( EventTarget , [], new . target ) as AbortSignal ; 822set ( signals , self , { 823aborted :false , 824reason :undefined , 825handler :null , 826algorithms :array <() => void >(), 827}); 828return self as AbortSignal ; 829} 830get aborted () { 831return state ( signals , this ). aborted ; 832} 833get reason () { 834return state ( signals , this ). reason ; 835} 836get onabort () { 837return state ( signals , this ). handler ; 838} 839set onabort ( value ) { 840const s = state ( signals , this ); 841value = typeof value === "function" ?value :null ; 842if ( ! s . handler && value ) { 843s . handlerListener = ( event ) => { 844if ( s . handler ) apply ( s . handler , this , [ event ]); 845}; 846addListener ( this , "abort" , s . handlerListener ! ); 847} else if ( s . handler && ! value ) { 848removeListener ( this , "abort" , s . handlerListener ! ); 849} 850s . handler = value ; 851} 852throwIfAborted () { 853const s = state ( signals , this ); 854if ( s . aborted ) throw s . reason ; 855} 856static abort ( reason ?:unknown ) :AbortSignal { 857const signal = new AbortSignal ( secret ); 858abort ( signal , reason ); 859return signal ; 860} 861static any ( sequence :unknown ) :AbortSignal { 862if ( 863sequence === null || 864( typeof sequence !== "object" && typeof sequence !== "function" ) 865) throw new TypeError ( "Expected a sequence of AbortSignals" ); 866const list = array < AbortSignal >(); 867for ( const signal of sequence as Iterable < unknown >) { 868state ( signals , signal ); 869push ( list , signal as AbortSignal ); 870} 871const result = new AbortSignal ( secret ); 872for ( let i = 0 ; i < list . length ; i ++ ) { 873if ( state ( signals , list [ i ]). aborted ) { 874abort ( result , state ( signals , list [ i ]). reason ); 875return result ; 876} 877} 878const weak = new WeakRef ( result ); 879for ( let i = 0 ; i < list . length ; i ++ ) { 880addAbort ( list [ i ], () => { 881const follower = deref ( weak ); 882if ( follower ) abort ( follower , state ( signals , list [ i ]). reason ); 883}); 884} 885return result ; 886} 887static timeout ( milliseconds :unknown ) :AbortSignal { 888required ( arguments . length , 1 ); 889const number = + ( milliseconds as number ), delay = trunc ( number ); 890if ( ! isFinite ( number ) || delay < 0 || delay >= 2 ** 64 ) { 891throw new TypeError ( "milliseconds is outside the accepted range" ); 892} 893const signal = new AbortSignal ( secret ); 894scheduleTimeout (() => { 895abort ( 896signal , 897createException ({ 898message :"The operation timed out" , 899name :"TimeoutError" , 900}), 901); 902}, delay ); 903return signal ; 904} 905} 906class AbortController { 907constructor () { 908set ( controllers , this , new AbortSignal ( secret )); 909} 910get signal () { 911return state ( controllers , this ); 912} 913abort ( reason ?:unknown ) :void { 914abort ( state ( controllers , this ), reason ); 915} 916} 917function followSignal ( signal :unknown ) :AbortSignal { 918const source = state ( signals , signal ), result = new AbortSignal ( secret ); 919if ( source . aborted ) abort ( result , source . reason ); 920else { 921const weak = new WeakRef ( result ); 922addAbort ( signal , () => { 923const follower = deref ( weak ); 924if ( follower ) abort ( follower , source . reason ); 925}); 926} 927return result ; 928} 929 930export { 931abort , 932AbortController , 933AbortSignal , 934addAbort , 935addListener , 936createException , 937CustomEvent , 938dataCloneError , 939dispatch , 940DOMException , 941ErrorEvent , 942Event , 943EventTarget , 944followSignal , 945hasListener , 946installGlobalEventTarget , 947isDispatching , 948observeListeners , 949preventDefault , 950PromiseRejectionEvent , 951removeListener , 952reportErrorValue , 953reportException , 954reportRejectionHandled , 955reportUnhandledRejection , 956secret , 957signals , 958};