mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-14 18:12:09 +08:00
feat: AbortController polyfill (#9333)
This commit is contained in:

committed by
Nathan Walker

parent
c4db847ded
commit
58442fb454
80
packages/core/abortcontroller/abortsignal.ts
Normal file
80
packages/core/abortcontroller/abortsignal.ts
Normal file
@ -0,0 +1,80 @@
|
||||
|
||||
import { Observable } from '../data/observable';
|
||||
|
||||
// Known Limitation
|
||||
// Use `any` because the type of `AbortSignal` in `lib.dom.d.ts` is wrong and
|
||||
// to make assignable our `AbortSignal` into that.
|
||||
// https://github.com/Microsoft/TSJS-lib-generator/pull/623
|
||||
type Events = {
|
||||
abort: any // Event & Type<"abort">
|
||||
}
|
||||
type EventAttributes = {
|
||||
onabort: any // Event & Type<"abort">
|
||||
}
|
||||
|
||||
/**
|
||||
* The signal class.
|
||||
* @see https://dom.spec.whatwg.org/#abortsignal
|
||||
*/
|
||||
export default class AbortSignal extends Observable {
|
||||
/**
|
||||
* AbortSignal cannot be constructed directly.
|
||||
*/
|
||||
public constructor() {
|
||||
super()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if this `AbortSignal`'s `AbortController` has signaled to abort, and `false` otherwise.
|
||||
*/
|
||||
public get aborted(): boolean {
|
||||
const aborted = abortedFlags.get(this)
|
||||
if (typeof aborted !== "boolean") {
|
||||
throw new TypeError(
|
||||
`Expected 'this' to be an 'AbortSignal' object, but got ${
|
||||
this === null ? "null" : typeof this
|
||||
}`,
|
||||
)
|
||||
}
|
||||
return aborted
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an AbortSignal object.
|
||||
*/
|
||||
export function createAbortSignal(): AbortSignal {
|
||||
const signal = new AbortSignal();
|
||||
abortedFlags.set(signal, false)
|
||||
return signal
|
||||
}
|
||||
|
||||
/**
|
||||
* Abort a given signal.
|
||||
*/
|
||||
export function abortSignal(signal: AbortSignal): void {
|
||||
if (abortedFlags.get(signal) !== false) {
|
||||
return
|
||||
}
|
||||
|
||||
abortedFlags.set(signal, true)
|
||||
signal.notify({ eventName: "abort", type: "abort" })
|
||||
}
|
||||
|
||||
/**
|
||||
* Aborted flag for each instances.
|
||||
*/
|
||||
const abortedFlags = new WeakMap<AbortSignal, boolean>()
|
||||
|
||||
// Properties should be enumerable.
|
||||
Object.defineProperties(AbortSignal.prototype, {
|
||||
aborted: { enumerable: true },
|
||||
})
|
||||
|
||||
// `toString()` should return `"[object AbortSignal]"`
|
||||
if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") {
|
||||
Object.defineProperty(AbortSignal.prototype, Symbol.toStringTag, {
|
||||
configurable: true,
|
||||
value: "AbortSignal",
|
||||
})
|
||||
}
|
62
packages/core/abortcontroller/index.ts
Normal file
62
packages/core/abortcontroller/index.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import AbortSignal, { abortSignal, createAbortSignal } from "./abortsignal"
|
||||
/**
|
||||
* The AbortController.
|
||||
* @see https://dom.spec.whatwg.org/#abortcontroller
|
||||
*/
|
||||
export default class AbortController {
|
||||
/**
|
||||
* Initialize this controller.
|
||||
*/
|
||||
public constructor() {
|
||||
signals.set(this, createAbortSignal())
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the `AbortSignal` object associated with this object.
|
||||
*/
|
||||
public get signal(): AbortSignal {
|
||||
return getSignal(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Abort and signal to any observers that the associated activity is to be aborted.
|
||||
*/
|
||||
public abort(): void {
|
||||
abortSignal(getSignal(this))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Associated signals.
|
||||
*/
|
||||
const signals = new WeakMap<AbortController, AbortSignal>()
|
||||
|
||||
/**
|
||||
* Get the associated signal of a given controller.
|
||||
*/
|
||||
function getSignal(controller: AbortController): AbortSignal {
|
||||
const signal = signals.get(controller)
|
||||
if (signal == null) {
|
||||
throw new TypeError(
|
||||
`Expected 'this' to be an 'AbortController' object, but got ${
|
||||
controller === null ? "null" : typeof controller
|
||||
}`,
|
||||
)
|
||||
}
|
||||
return signal
|
||||
}
|
||||
|
||||
// Properties should be enumerable.
|
||||
Object.defineProperties(AbortController.prototype, {
|
||||
signal: { enumerable: true },
|
||||
abort: { enumerable: true },
|
||||
})
|
||||
|
||||
if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") {
|
||||
Object.defineProperty(AbortController.prototype, Symbol.toStringTag, {
|
||||
configurable: true,
|
||||
value: "AbortController",
|
||||
})
|
||||
}
|
||||
|
||||
export { AbortController, AbortSignal }
|
@ -319,6 +319,9 @@ export function initGlobal() {
|
||||
global.registerModule('fetch', () => require('../fetch'));
|
||||
installPolyfills('fetch', ['fetch', 'Headers', 'Request', 'Response']);
|
||||
|
||||
global.registerModule('abortcontroller', () => require('../abortcontroller'));
|
||||
installPolyfills('abortcontroller', ['AbortController', 'AbortSignal']);
|
||||
|
||||
// Custom decorators
|
||||
|
||||
global.Deprecated = function (target: Object, key?: string | symbol, descriptor?: any) {
|
||||
|
Reference in New Issue
Block a user