2021-01-11 12:13:41 -05:00
|
|
|
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
2021-02-04 17:18:32 -05:00
|
|
|
"use strict";
|
2020-07-19 13:49:44 -04:00
|
|
|
|
|
|
|
((window) => {
|
2020-09-16 16:22:43 -04:00
|
|
|
const core = window.Deno.core;
|
2020-07-19 13:49:44 -04:00
|
|
|
const { build } = window.__bootstrap.build;
|
2020-12-16 11:14:12 -05:00
|
|
|
const { errors } = window.__bootstrap.errors;
|
2021-07-03 18:17:52 -04:00
|
|
|
const {
|
|
|
|
Error,
|
|
|
|
Promise,
|
|
|
|
PromisePrototypeThen,
|
|
|
|
PromiseResolve,
|
|
|
|
SymbolAsyncIterator,
|
|
|
|
} = window.__bootstrap.primordials;
|
2020-07-19 13:49:44 -04:00
|
|
|
|
|
|
|
function bindSignal(signo) {
|
2021-04-12 15:55:05 -04:00
|
|
|
return core.opSync("op_signal_bind", signo);
|
2020-07-19 13:49:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
function pollSignal(rid) {
|
2021-04-12 15:55:05 -04:00
|
|
|
return core.opAsync("op_signal_poll", rid);
|
2020-07-19 13:49:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
function unbindSignal(rid) {
|
2021-04-12 15:55:05 -04:00
|
|
|
core.opSync("op_signal_unbind", rid);
|
2020-07-19 13:49:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
function signal(signo) {
|
|
|
|
if (build.os === "windows") {
|
2021-09-07 07:17:44 -04:00
|
|
|
throw new Error("Signal API is not implemented for Windows");
|
2020-07-19 13:49:44 -04:00
|
|
|
}
|
|
|
|
return new SignalStream(signo);
|
|
|
|
}
|
|
|
|
|
|
|
|
class SignalStream {
|
|
|
|
#disposed = false;
|
2021-07-03 18:17:52 -04:00
|
|
|
#pollingPromise = PromiseResolve(false);
|
2020-07-19 13:49:44 -04:00
|
|
|
#rid = 0;
|
|
|
|
|
|
|
|
constructor(signo) {
|
2021-04-05 12:40:24 -04:00
|
|
|
this.#rid = bindSignal(signo);
|
2020-07-19 13:49:44 -04:00
|
|
|
this.#loop();
|
|
|
|
}
|
|
|
|
|
|
|
|
#pollSignal = async () => {
|
2021-04-05 12:40:24 -04:00
|
|
|
let done;
|
2020-12-16 11:14:12 -05:00
|
|
|
try {
|
2021-04-05 12:40:24 -04:00
|
|
|
done = await pollSignal(this.#rid);
|
2020-12-16 11:14:12 -05:00
|
|
|
} catch (error) {
|
|
|
|
if (error instanceof errors.BadResource) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
throw error;
|
|
|
|
}
|
2021-04-05 12:40:24 -04:00
|
|
|
return done;
|
2020-07-19 13:49:44 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
#loop = async () => {
|
|
|
|
do {
|
|
|
|
this.#pollingPromise = this.#pollSignal();
|
|
|
|
} while (!(await this.#pollingPromise) && !this.#disposed);
|
|
|
|
};
|
|
|
|
|
|
|
|
then(
|
|
|
|
f,
|
|
|
|
g,
|
|
|
|
) {
|
2021-07-03 18:17:52 -04:00
|
|
|
const p = PromisePrototypeThen(this.#pollingPromise, (done) => {
|
2021-06-22 02:17:44 -04:00
|
|
|
if (done) {
|
|
|
|
// If pollingPromise returns true, then
|
|
|
|
// this signal stream is finished and the promise API
|
|
|
|
// should never be resolved.
|
|
|
|
return new Promise(() => {});
|
|
|
|
}
|
|
|
|
return;
|
2021-07-03 18:17:52 -04:00
|
|
|
});
|
|
|
|
return PromisePrototypeThen(p, f, g);
|
2020-07-19 13:49:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
async next() {
|
|
|
|
return { done: await this.#pollingPromise, value: undefined };
|
|
|
|
}
|
|
|
|
|
2021-07-03 18:17:52 -04:00
|
|
|
[SymbolAsyncIterator]() {
|
2020-07-19 13:49:44 -04:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
dispose() {
|
|
|
|
if (this.#disposed) {
|
|
|
|
throw new Error("The stream has already been disposed.");
|
|
|
|
}
|
|
|
|
this.#disposed = true;
|
|
|
|
unbindSignal(this.#rid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
window.__bootstrap.signals = {
|
|
|
|
signal,
|
|
|
|
SignalStream,
|
|
|
|
};
|
|
|
|
})(this);
|