mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-05 07:18:39 +09:00
Backport Basilisk internal userscripts
This commit is contained in:
parent
15bec18421
commit
5c168f64fc
23 changed files with 2648 additions and 0 deletions
|
|
@ -0,0 +1,208 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
// ==UserScript==
|
||||
// @name ReadableStream pipeThrough Polyfill (best-effort)
|
||||
// @namespace internal-userscripts
|
||||
// @description Adds ReadableStream.prototype.pipeThrough using pipeTo or reader/writer pumping when missing.
|
||||
// @match *://*/*
|
||||
// @grant none
|
||||
// @run-at document-start
|
||||
// ==/UserScript==
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var global = typeof window !== "undefined" ? window : null;
|
||||
if (!global || !global.ReadableStream || !global.ReadableStream.prototype) {
|
||||
return;
|
||||
}
|
||||
var existingPipeThrough = global.ReadableStream.prototype.pipeThrough;
|
||||
if (typeof existingPipeThrough === "function") {
|
||||
if (typeof global.TransformStream !== "function") {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
var probeStream = new global.ReadableStream({
|
||||
start: function (controller) {
|
||||
controller.close();
|
||||
}
|
||||
});
|
||||
probeStream.pipeThrough(new global.TransformStream(), { preventClose: true });
|
||||
return;
|
||||
} catch (e) {
|
||||
if (String(e).indexOf("not yet implemented") === -1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var PromiseCtor = global.Promise;
|
||||
if (typeof PromiseCtor !== "function") {
|
||||
return;
|
||||
}
|
||||
|
||||
function isObject(value) {
|
||||
return value !== null && (typeof value === "object" || typeof value === "function");
|
||||
}
|
||||
|
||||
function getTransformStream(transform, name) {
|
||||
var stream = transform[name];
|
||||
if (!isObject(stream)) {
|
||||
throw new TypeError("pipeThrough requires a transform stream with " + name);
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
function startPipeWithReader(source, writable, options) {
|
||||
var reader = source.getReader();
|
||||
var writer = writable.getWriter();
|
||||
var preventClose = options && options.preventClose;
|
||||
var preventAbort = options && options.preventAbort;
|
||||
var preventCancel = options && options.preventCancel;
|
||||
var signal = options && options.signal;
|
||||
var abortHandler = null;
|
||||
|
||||
function safeReleaseLock(stream, maybeReader, lockedProp) {
|
||||
if (!maybeReader) {
|
||||
return;
|
||||
}
|
||||
var isLocked = true;
|
||||
if (typeof lockedProp === "function") {
|
||||
try {
|
||||
var lockedValue = lockedProp();
|
||||
if (typeof lockedValue === "boolean") {
|
||||
isLocked = lockedValue;
|
||||
}
|
||||
} catch (e) {
|
||||
isLocked = true;
|
||||
}
|
||||
}
|
||||
if (!isLocked) {
|
||||
return;
|
||||
}
|
||||
var releaseFn = null;
|
||||
try {
|
||||
releaseFn = maybeReader.releaseLock;
|
||||
} catch (e) {
|
||||
releaseFn = null;
|
||||
}
|
||||
if (typeof releaseFn === "function") {
|
||||
try { releaseFn.call(maybeReader); } catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
function releaseLocks() {
|
||||
safeReleaseLock(source, reader, function () { return source.locked; });
|
||||
safeReleaseLock(writable, writer, function () { return writable.locked; });
|
||||
reader = null;
|
||||
writer = null;
|
||||
}
|
||||
|
||||
function cleanupAbort() {
|
||||
if (abortHandler && signal && typeof signal.removeEventListener === "function") {
|
||||
signal.removeEventListener("abort", abortHandler);
|
||||
}
|
||||
}
|
||||
|
||||
if (signal) {
|
||||
abortHandler = function () {
|
||||
var reason = signal.reason;
|
||||
if (!preventCancel) {
|
||||
try { reader.cancel(reason); } catch (e) {}
|
||||
}
|
||||
if (!preventAbort) {
|
||||
try { writer.abort(reason); } catch (e) {}
|
||||
}
|
||||
};
|
||||
if (signal.aborted) {
|
||||
abortHandler();
|
||||
cleanupAbort();
|
||||
releaseLocks();
|
||||
return;
|
||||
}
|
||||
if (typeof signal.addEventListener === "function") {
|
||||
signal.addEventListener("abort", abortHandler);
|
||||
}
|
||||
}
|
||||
|
||||
function pump() {
|
||||
var readPromise;
|
||||
try {
|
||||
readPromise = reader.read();
|
||||
} catch (e) {
|
||||
return PromiseCtor.reject(e);
|
||||
}
|
||||
return readPromise.then(function (result) {
|
||||
if (result.done) {
|
||||
if (!preventClose) {
|
||||
var closePromise;
|
||||
try {
|
||||
closePromise = writer.close();
|
||||
} catch (e) {
|
||||
return PromiseCtor.reject(e);
|
||||
}
|
||||
return PromiseCtor.resolve(closePromise);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
var writePromise;
|
||||
try {
|
||||
writePromise = writer.write(result.value);
|
||||
} catch (e) {
|
||||
return PromiseCtor.reject(e);
|
||||
}
|
||||
return PromiseCtor.resolve(writePromise).then(pump);
|
||||
});
|
||||
}
|
||||
|
||||
pump().catch(function (err) {
|
||||
if (!preventCancel) {
|
||||
try { reader.cancel(err); } catch (e) {}
|
||||
}
|
||||
if (!preventAbort) {
|
||||
try { writer.abort(err); } catch (e) {}
|
||||
}
|
||||
}).then(function () {
|
||||
cleanupAbort();
|
||||
releaseLocks();
|
||||
}, function () {
|
||||
cleanupAbort();
|
||||
releaseLocks();
|
||||
});
|
||||
}
|
||||
|
||||
function pipeThrough(transform, options) {
|
||||
if (!isObject(this)) {
|
||||
throw new TypeError("ReadableStream.prototype.pipeThrough called on incompatible receiver");
|
||||
}
|
||||
if (!isObject(transform)) {
|
||||
throw new TypeError("pipeThrough requires a transform stream");
|
||||
}
|
||||
var readable = getTransformStream(transform, "readable");
|
||||
var writable = getTransformStream(transform, "writable");
|
||||
var source = this;
|
||||
|
||||
if (typeof source.pipeTo === "function") {
|
||||
var pipePromise = source.pipeTo(writable, options);
|
||||
if (pipePromise && typeof pipePromise.catch === "function") {
|
||||
pipePromise.catch(function () {});
|
||||
}
|
||||
} else if (typeof source.getReader === "function" && typeof writable.getWriter === "function") {
|
||||
startPipeWithReader(source, writable, options);
|
||||
} else {
|
||||
throw new TypeError("ReadableStream.prototype.pipeThrough is not supported");
|
||||
}
|
||||
|
||||
return readable;
|
||||
}
|
||||
|
||||
Object.defineProperty(global.ReadableStream.prototype, "pipeThrough", {
|
||||
value: pipeThrough,
|
||||
writable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
try {
|
||||
global.__internalUserscriptsReadableStreamPipeThroughPolyfill = true;
|
||||
} catch (e) {}
|
||||
})();
|
||||
Loading…
Add table
Add a link
Reference in a new issue