此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.gf.qytechs.cn/scripts/17895/142141/polyfill.js
你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式
(我已經安裝了使用者樣式管理器,讓我安裝!)
// ==UserScript==
// @name polyfill
// @description Firefox、Opera、Google Chrome向けのpolyfillです。
// @version 1.5.0
// @license Mozilla Public License Version 2.0 (MPL 2.0); https://www.mozilla.org/MPL/2.0/
// @compatible Firefox
// @compatible Opera
// @compatible Chrome
// @author 100の人
// @homepage https://gf.qytechs.cn/scripts/17895
// ==/UserScript==
(function () {
'use strict';
// Polyfill for Firefox, Opera, and Google Chrome
if (!('prepend' in document)) {
/**
* 複数のインターフェースに[Unscopable]拡張属性を伴うメンバーを実装します。
* @param {Function[]} interfaces
* @param {Object.<Function>} members
*/
let implementUnscopableMembers = function (interfaces, members) {
for (let i_f of interfaces) {
Object.assign(i_f.prototype, members);
if (Symbol.unscopables) {
let object = {};
for (let memberName of Object.keys(members)) {
object[memberName] = true;
}
if (i_f.prototype[Symbol.unscopables]) {
Object.assign(i_f.prototype[Symbol.unscopables], object);
} else {
i_f.prototype[Symbol.unscopables] = object;
}
}
}
};
/**
* @see [DOM Standard]{@link https://dom.spec.whatwg.org/#converting-nodes-into-a-node}
* @param {(Node|string)[]} nodes
* @returns {(Node|DocumentFragment)}
*/
let convertNodesIntoNode = function (nodes) {
for (let i = 0, l = nodes.length; i < l; i++) {
if (!(nodes[i] instanceof Node)) {
nodes[i] = new Text(nodes[i]);
}
}
if (nodes.length === 1) {
return nodes[0];
}
let fragment = new DocumentFragment();
for (let node of nodes) {
fragment.appendChild(node);
}
return fragment;
};
// https://dom.spec.whatwg.org/#interface-parentnode
implementUnscopableMembers([Document, DocumentFragment, Element], {
/**
* Inserts nodes before the first child of node, while replacing strings in nodes with equivalent Text nodes.
* @see [DOM Standard]{@link https://dom.spec.whatwg.org/#dom-parentnode-prepend}
* @param {...(Node|string)} nodes
* @throws {DOMException} Throws a HierarchyRequestError if the constraints of the node tree are violated.
*/
prepend(...nodes) {
this.insertBefore(convertNodesIntoNode(nodes), this.firstChild);
},
/**
* Inserts nodes after the last child of node, while replacing strings in nodes with equivalent Text nodes.
* @see [DOM Standard]{@link https://dom.spec.whatwg.org/#dom-parentnode-append}
* @param {...(Node|string)} nodes
* @throws {DOMException} Throws a HierarchyRequestError if the constraints of the node tree are violated.
*/
append(...nodes) {
this.appendChild(convertNodesIntoNode(nodes));
},
});
// https://dom.spec.whatwg.org/#interface-childnode
implementUnscopableMembers([DocumentType, Element, CharacterData], {
/**
* Inserts nodes just before node, while replacing strings in nodes with equivalent Text nodes.
* @see [DOM Standard]{@link https://dom.spec.whatwg.org/#dom-childnode-before}
* @param {...(Node|string)} nodes
* @throws {DOMException} Throws a HierarchyRequestError if the constraints of the node tree are violated.
*/
before(...nodes) {
let parent = this.parentNode;
if (!parent) {
return;
}
let viablePreviousSibling;
while ((viablePreviousSibling = this.previousSibling) && nodes.includes(viablePreviousSibling)) {
}
parent.insertBefore(
convertNodesIntoNode(nodes),
viablePreviousSibling ? viablePreviousSibling.nextSibling : parent.firstChild
);
},
/**
* Inserts nodes just after node, while replacing strings in nodes with equivalent Text nodes.
* @see [DOM Standard]{@link https://dom.spec.whatwg.org/#dom-childnode-after}
* @param {...(Node|string)} nodes
* @throws {DOMException} Throws a HierarchyRequestError if the constraints of the node tree are violated.
*/
after(...nodes) {
let parent = this.parentNode;
if (!parent) {
return;
}
let viableNextSibling;
while ((viableNextSibling = this.nextSibling) && nodes.includes(viableNextSibling)) {
}
parent.insertBefore(convertNodesIntoNode(nodes), viableNextSibling);
},
/**
* Replaces node with nodes, while replacing strings in nodes with equivalent Text nodes.
* @see [DOM Standard]{@link https://dom.spec.whatwg.org/#dom-childnode-replacewith}
* @param {...(Node|string)} nodes
* @throws {DOMException} Throws a HierarchyRequestError if the constraints of the node tree are violated.
*/
replaceWith(...nodes) {
let parent = this.parentNode;
if (!parent) {
return;
}
let viableNextSibling;
while ((viableNextSibling = this.nextSibling) && nodes.includes(viableNextSibling)) {
}
let node = convertNodesIntoNode(nodes);
if (this.parentNode === parent) {
parent.replaceChild(node, this);
} else {
parent.insertBefore(node, viableNextSibling);
}
},
});
}
if (new URLSearchParams('?').has('?')) {
URLSearchParams = new Proxy(URLSearchParams, {
construct(URLSearchParams, argumentsList) {
if (argumentsList.length > 0 && !(argumentsList[0] instanceof URLSearchParams)) {
argumentsList[0] = String(argumentsList[0]).replace(/^\?/, '');
}
return new URLSearchParams(...argumentsList);
},
});
}
if (!('createFor' in URL)) {
/**
* 分をミリ秒に変換するときの乗数。
* @constant {number}
*/
const MINUTES_TO_MILISECONDS = 60 * 1000;
/**
* Blob URL を自動破棄するまでのミリ秒数。
* @constant {number}
*/
const MAX_LIFETIME = 10 * MINUTES_TO_MILISECONDS;
/**
* Blob URLを生成し、{@link MAX_LIFETIME}ミリ秒後に破棄します。
* @see [File API]{@link https://www.w3.org/TR/FileAPI/#dfn-createFor}
* @see [Bug 1062917 - Implement URL.createFor]{@link https://bugzilla.mozilla.org/show_bug.cgi?id=1062917}
* @see [Issue 608460 - chromium - Consider implementing URL.createFor() - Monorail]{@link https://bugs.chromium.org/p/chromium/issues/detail?id=608460}
* @param {Blob} blob
* @returns {string} Blob URL。
*/
URL.createFor = function (blob) {
let url = this.createObjectURL(blob);
window.setTimeout(() => this.revokeObjectURL(url), MAX_LIFETIME);
return url;
};
}
// Polyfill for Firefox
// 6.4 Time Zone Names | ECMAScript® 2016 Internationalization API Specification
// http://www.ecma-international.org/ecma-402/3.0/index.html#sec-time-zone-names
// Bug 837961 – Add support for IANA time zone names to internationalization API
// <https://bugzilla.mozilla.org/show_bug.cgi?id=837961>
// メモ:JavaScript で システム時刻から別のタイムゾーンの時刻へ変換 — ねじろぐ @drillbits
// <http://d.hatena.ne.jp/drillbits/20100127/javascript_timezone_system>
try {
new Intl.DateTimeFormat('ja', {timeZone: 'Asia/Tokyo'});
} catch (exception) {
/**
* 大文字化したタイムゾーン名とタイムゾーンオフセットの組。
* @constant {Object.<number>}
*/
const TIMEZONE_OFFSETS = {
'ASIA/TOKYO': -540,
};
/**
* 分をミリ秒に変換するときの乗数。
* @constant {number}
*/
const MINUTES_TO_MILLISECONDS = 60 * 1000;
Date.prototype.toLocaleString = new Proxy(Date.prototype.toLocaleString, {
apply: function (target, thisArg, argumentsList) {
if (typeof argumentsList[1] === 'object' && argumentsList[1] !== null) {
let timeZone = String(argumentsList[1].timeZone).toUpperCase();
if (TIMEZONE_OFFSETS.hasOwnProperty(timeZone)) {
let timeZoneOffset = TIMEZONE_OFFSETS[timeZone];
if (thisArg.getTimezoneOffset() === timeZoneOffset) {
delete argumentsList[1].timeZone;
} else {
thisArg = new Date(thisArg.getTime() - timeZoneOffset * MINUTES_TO_MILLISECONDS);
argumentsList[1].timeZone = 'UTC';
}
}
}
return target.apply(thisArg, argumentsList);
},
});
}
// For Firefox 45 ESR
try {
new CustomEvent('', {detail: {}});
} catch (exception) {
CustomEvent = new Proxy(CustomEvent, { construct: function (target, args) {
if (args.length >= 2
&& typeof args[1] === 'object' && typeof args[1].detail === 'object' && args[1].detail !== null) {
args[1].detail = cloneInto(args[1].detail, window, {
cloneFunctions: true,
wrapReflectors: true,
});
}
return new target(...args);
} });
}
})();