UV Added! (Repl support not a given yet)

This commit is contained in:
QuiteAFancyEmerald 2022-02-28 15:17:03 -08:00
parent d70d202131
commit ec78402863
14 changed files with 772 additions and 199 deletions

View file

@ -32,7 +32,7 @@ const pages = {
'rh': 'pages/proxnav/rammerhead.html', 'rh': 'pages/proxnav/rammerhead.html',
'w': 'pages/proxnav/womginx.html', 'w': 'pages/proxnav/womginx.html',
/* Proxy Presets */ /* Proxy Presets */
'sx': 'pages/proxnav/preset/searx.html', 'sx': 'pages/proxnav/preset/spotify.html',
'y': 'pages/proxnav/preset/youtube.html', 'y': 'pages/proxnav/preset/youtube.html',
'd': 'pages/proxnav/preset/discord.html', 'd': 'pages/proxnav/preset/discord.html',
'r': 'pages/proxnav/preset/reddit.html', 'r': 'pages/proxnav/preset/reddit.html',

View file

@ -7,7 +7,6 @@ import pkg from './routes.mjs';
import { paintSource, tryReadFile } from './randomization.mjs'; import { paintSource, tryReadFile } from './randomization.mjs';
const bare = new Server('/bare/', ''); const bare = new Server('/bare/', '');
const config = JSON.parse(await readFile(new URL('./config.json', const config = JSON.parse(await readFile(new URL('./config.json',
import.meta.url))); import.meta.url)));
const { pages, text404 } = pkg; const { pages, text404 } = pkg;
@ -18,12 +17,10 @@ const router = express.Router();
const server = http.createServer(app); const server = http.createServer(app);
router.get('/', async(req, res) => res.send(paintSource(tryReadFile(path.normalize(__dirname + '/views/' + (['/', '/?'].includes(req.url) ? pages.index : pages[Object.keys(req.query)[0]])))))); router.get('/', async(req, res) => res.send(paintSource(tryReadFile(path.normalize(__dirname + '/views/' + (['/', '/?'].includes(req.url) ? pages.index : pages[Object.keys(req.query)[0]]))))));
app.use('/', (req, res, next) => {
if (!bare.route_request(req, res)) return next()
});
app.use(router); app.use(router);
app.use('/', (req, res, next) => {
if (!bare.route_request(req, res)) return next()
});
app.use(express.static(path.normalize(__dirname + '/views'))); app.use(express.static(path.normalize(__dirname + '/views')));
app.disable('x-powered-by'); app.disable('x-powered-by');
app.use((req, res) => { app.use((req, res) => {
@ -31,4 +28,4 @@ app.use((req, res) => {
}); });
server.listen(port); server.listen(port);
console.log('Holy Unblocker is listening on port ' + port + '.'); console.log('Holy Unblocker is listening on port ' + port + '.');

View file

@ -1 +1 @@
document.getElementById("header").innerHTML = decodeURIComponent(atob("JTNDYSUyMGhyZWYlM0QlMjIlMkYlMjIlMjBjbGFzcyUzRCUyMmJyYW5kJTIyJTNFSCUyNiUyMzE3MyUzQm8lMjYlMjMxNzMlM0JseSUyMFUlMjYlMjMxNzMlM0JuJTI2JTIzMTczJTNCYiUyNiUyMzE3MyUzQmxvJTI2JTIzMTczJTNCYyUyNiUyMzE3MyUzQmslMjYlMjMxNzMlM0JlciUzQyUyRmElM0UlM0NpbnB1dCUyMGlkJTNEJTIybW5hdmVjYiUyMiUyMHR5cGUlM0QlMjJjaGVja2JveCUyMiUzRSUzQ2xhYmVsJTIwZm9yJTNEJTIybW5hdmVjYiUyMiUyMGNsYXNzJTNEJTIybW5hdmUlMjIlM0UlM0NzcGFuJTIwY2xhc3MlM0QlMjJtbmF2ZWJ1dHRvbiUyMiUzRSUzQyUyRnNwYW4lM0UlM0MlMkZsYWJlbCUzRSUzQ3VsJTIwY2xhc3MlM0QlMjJuYXZiYXIlMjIlM0UlMjAlM0NsaSUzRSUzQ2ElMjBocmVmJTNEJTIyJTJGJTNGeiUyMiUzRVclMjYlMjMxNzMlM0JlYiUyMFByJTI2JTIzMTczJTNCb3glMjYlMjMxNzMlM0JpZSUyNiUyMzE3MyUzQnMlM0MlMkZhJTNFJTNDJTJGbGklM0UlM0NsaSUzRSUzQ2ElMjBocmVmJTNEJTIyJTJGJTNGc3glMjIlM0VTZWFyeCUzQyUyRmElM0UlM0MlMkZsaSUzRSUzQ2xpJTNFJTNDYSUyMGhyZWYlM0QlMjIlMkYlM0ZnJTIyJTNFRyUyNiUyMzE3MyUzQmElMjYlMjMxNzMlM0JtZSUyNiUyMzE3MyUzQnMlM0MlMkZhJTNFJTNDJTJGbGklM0UlM0NsaSUzRSUzQ2ElMjBocmVmJTNEJTIyJTJGJTNGeSUyMiUzRVlvJTI2JTIzMTczJTNCdVQlMjYlMjMxNzMlM0J1JTI2JTIzMTczJTNCYmUlM0MlMkZhJTNFJTNDJTJGbGklM0UlM0NsaSUzRSUzQ2ElMjBocmVmJTNEJTIyJTJGJTNGZCUyMiUzRUQlMjYlMjMxNzMlM0Jpc2MlMjYlMjMxNzMlM0JvciUyNiUyMzE3MyUzQmQlM0MlMkZhJTNFJTNDJTJGbGklM0UlM0NsaSUzRSUzQ2ElMjBocmVmJTNEJTIyJTJGJTNGciUyMiUzRVJlJTI2JTIzMTczJTNCZGQlMjYlMjMxNzMlM0JpdCUzQyUyRmElM0UlM0MlMkZsaSUzRSUzQ2xpJTIwY2xhc3MlM0QlMjJkcm9wZG93bi1wYXJlbnQlMjIlM0UlM0NhJTIwaHJlZiUzRCUyMiUyMyUyMiUzRU0lMjYlMjMxNzMlM0JvciUyNiUyMzE3MyUzQmUlMjAlM0NpJTIwY2xhc3MlM0QlMjJmYXMlMjBmYS1lbGxpcHNpcy12JTIyJTNFJTNDJTJGaSUzRSUzQyUyRmElM0UlMjAlM0NkaXYlMjBjbGFzcyUzRCUyMmRyb3Bkb3duLWNoaWxkJTIyJTIwdGFiaW5kZXglM0QlMjIwJTIyJTNFJTIwJTNDdWwlMjBjbGFzcyUzRCUyMnN1Ym5hdmJhciUyMiUzRSUyMCUzQ2klMjBjbGFzcyUzRCUyMmZhcyUyMGZhLWJhcnMlMjIlM0UlM0MlMkZpJTNFJTIwJTNDbGklM0UlM0NhJTIwaHJlZiUzRCUyMiUyRiUzRnglMjIlM0VCb29rJTI2JTIzMTczJTNCbWFyayUyNiUyMzE3MyUzQmxldHMlM0MlMkZhJTNFJTNDJTJGbGklM0UlM0NsaSUzRSUzQ2ElMjBocmVmJTNEJTIyJTJGJTNGaW4lMjIlM0VEb2NzJTNDJTJGYSUzRSUzQyUyRmxpJTNFJTNDbGklM0UlM0NhJTIwaHJlZiUzRCUyMiUyRiUzRmZhcSUyMiUzRUZBJTI2JTIzMTczJTNCUSUzQyUyRmElM0UlM0MlMkZsaSUzRSUzQ2xpJTNFJTNDYSUyMGhyZWYlM0QlMjIlMkYlM0ZjJTIyJTNFQ3JlZGl0JTI2JTIzMTczJTNCcyUzQyUyRmElM0UlM0MlMkZsaSUzRSUzQ2xpJTNFJTNDYSUyMGhyZWYlM0QlMjIlMkYlM0Z0JTIyJTNFVE8lMjYlMjMxNzMlM0JTJTNDJTJGYSUzRSUzQyUyRmxpJTNFJTNDJTJGdWwlM0UlMjAlM0MlMkZkaXYlM0UlM0MlMkZsaSUzRSUzQ2xpJTIwY2xhc3MlM0QlMjJkcm9wZG93bi1wYXJlbnQlMjIlM0UlM0NhJTIwaHJlZiUzRCUyMiUyMyUyMiUzRVNldHRpbmdzJTIwJTNDaSUyMGNsYXNzJTNEJTIyZmFzJTIwZmEtY29nJTIyJTNFJTNDJTJGaSUzRSUzQyUyRmElM0UlMjAlM0NkaXYlMjBjbGFzcyUzRCUyMmRyb3Bkb3duLWNoaWxkJTIyJTIwdGFiaW5kZXglM0QlMjIwJTIyJTNFJTIwJTNDZGl2JTIwaWQlM0QlMjJjc2VsJTIyJTNFJTNDJTJGZGl2JTNFJTNDJTJGZGl2JTNFJTNDJTJGbGklM0UlM0MlMkZ1bCUzRQ==")); document.getElementById("header").innerHTML = decodeURIComponent(atob("JTNDYSUyMGhyZWYlM0QlMjIlMkYlMjIlMjBjbGFzcyUzRCUyMmJyYW5kJTIyJTNFSCUyNiUyMzE3MyUzQm8lMjYlMjMxNzMlM0JseSUyMFUlMjYlMjMxNzMlM0JuJTI2JTIzMTczJTNCYiUyNiUyMzE3MyUzQmxvJTI2JTIzMTczJTNCYyUyNiUyMzE3MyUzQmslMjYlMjMxNzMlM0JlciUzQyUyRmElM0UlMEElM0NpbnB1dCUyMGlkJTNEJTIybW5hdmVjYiUyMiUyMHR5cGUlM0QlMjJjaGVja2JveCUyMiUzRSUwQSUzQ2xhYmVsJTIwZm9yJTNEJTIybW5hdmVjYiUyMiUyMGNsYXNzJTNEJTIybW5hdmUlMjIlM0UlM0NzcGFuJTIwY2xhc3MlM0QlMjJtbmF2ZWJ1dHRvbiUyMiUzRSUzQyUyRnNwYW4lM0UlM0MlMkZsYWJlbCUzRSUwQSUzQ3VsJTIwY2xhc3MlM0QlMjJuYXZiYXIlMjIlM0UlMEElMjAlMjAlMjAlMjAlM0NsaSUzRSUzQ2ElMjBocmVmJTNEJTIyJTJGJTNGeiUyMiUzRVclMjYlMjMxNzMlM0JlYiUyMFByJTI2JTIzMTczJTNCb3glMjYlMjMxNzMlM0JpZSUyNiUyMzE3MyUzQnMlM0MlMkZhJTNFJTNDJTJGbGklM0UlMEElMjAlMjAlMjAlMjAlM0NsaSUzRSUzQ2ElMjBocmVmJTNEJTIyJTJGJTNGZyUyMiUzRUclMjYlMjMxNzMlM0JhJTI2JTIzMTczJTNCbWUlMjYlMjMxNzMlM0JzJTNDJTJGYSUzRSUzQyUyRmxpJTNFJTBBJTIwJTIwJTIwJTIwJTNDbGklM0UlM0NhJTIwaHJlZiUzRCUyMiUyRiUzRnN4JTIyJTNFUyUyNiUyMzE3MyUzQnBvdGklMjYlMjMxNzMlM0JmeSUzQyUyRmElM0UlM0MlMkZsaSUzRSUwQSUyMCUyMCUyMCUyMCUzQ2xpJTNFJTNDYSUyMGhyZWYlM0QlMjIlMkYlM0Z5JTIyJTNFWW8lMjYlMjMxNzMlM0J1VCUyNiUyMzE3MyUzQnUlMjYlMjMxNzMlM0JiZSUzQyUyRmElM0UlM0MlMkZsaSUzRSUwQSUyMCUyMCUyMCUyMCUzQ2xpJTNFJTNDYSUyMGhyZWYlM0QlMjIlMkYlM0ZkJTIyJTNFRCUyNiUyMzE3MyUzQmlzYyUyNiUyMzE3MyUzQm9yJTI2JTIzMTczJTNCZCUzQyUyRmElM0UlM0MlMkZsaSUzRSUwQSUyMCUyMCUyMCUyMCUzQ2xpJTNFJTNDYSUyMGhyZWYlM0QlMjIlMkYlM0ZyJTIyJTNFUmUlMjYlMjMxNzMlM0JkZCUyNiUyMzE3MyUzQml0JTNDJTJGYSUzRSUzQyUyRmxpJTNFJTBBJTIwJTIwJTIwJTIwJTNDIS0tJTIwdGFiaW5kZXglM0QlMjIwJTIyJTIwaXMlMjByZXF1aXJlZCUyMG9uJTIwdGhlJTIwZHJvcGRvd25zJTIwLS0lM0UlMEElMjAlMjAlMjAlMjAlM0NsaSUyMGNsYXNzJTNEJTIyZHJvcGRvd24tcGFyZW50JTIyJTNFJTNDYSUyMGhyZWYlM0QlMjIlMjMlMjIlM0VNJTI2JTIzMTczJTNCb3IlMjYlMjMxNzMlM0JlJTIwJTNDaSUyMGNsYXNzJTNEJTIyZmFzJTIwZmEtZWxsaXBzaXMtdiUyMiUzRSUzQyUyRmklM0UlM0MlMkZhJTNFJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTNDZGl2JTIwY2xhc3MlM0QlMjJkcm9wZG93bi1jaGlsZCUyMiUyMHRhYmluZGV4JTNEJTIyMCUyMiUzRSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUzQ3VsJTIwY2xhc3MlM0QlMjJzdWJuYXZiYXIlMjIlM0UlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlM0NpJTIwY2xhc3MlM0QlMjJmYXMlMjBmYS1iYXJzJTIyJTNFJTNDJTJGaSUzRSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUzQ2xpJTNFJTNDYSUyMGhyZWYlM0QlMjIlMkYlM0Z4JTIyJTNFQm9vayUyNiUyMzE3MyUzQm1hcmslMjYlMjMxNzMlM0JsZXRzJTNDJTJGYSUzRSUzQyUyRmxpJTNFJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTNDbGklM0UlM0NhJTIwaHJlZiUzRCUyMiUyRiUzRmluJTIyJTNFRG9jcyUzQyUyRmElM0UlM0MlMkZsaSUzRSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUzQ2xpJTNFJTNDYSUyMGhyZWYlM0QlMjIlMkYlM0ZmYXElMjIlM0VGQSUyNiUyMzE3MyUzQlElM0MlMkZhJTNFJTNDJTJGbGklM0UlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlM0NsaSUzRSUzQ2ElMjBocmVmJTNEJTIyJTJGJTNGYyUyMiUzRUNyZWRpdCUyNiUyMzE3MyUzQnMlM0MlMkZhJTNFJTNDJTJGbGklM0UlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlM0NsaSUzRSUzQ2ElMjBocmVmJTNEJTIyJTJGJTNGdCUyMiUzRVRPJTI2JTIzMTczJTNCUyUzQyUyRmElM0UlM0MlMkZsaSUzRSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUzQyUyRnVsJTNFJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTNDJTJGZGl2JTNFJTBBJTIwJTIwJTIwJTIwJTNDJTJGbGklM0UlMEElMjAlMjAlMjAlMjAlM0NsaSUyMGNsYXNzJTNEJTIyZHJvcGRvd24tcGFyZW50JTIyJTNFJTNDYSUyMGhyZWYlM0QlMjIlMjMlMjIlM0VTZXR0aW5ncyUyMCUzQ2klMjBjbGFzcyUzRCUyMmZhcyUyMGZhLWNvZyUyMiUzRSUzQyUyRmklM0UlM0MlMkZhJTNFJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTNDZGl2JTIwY2xhc3MlM0QlMjJkcm9wZG93bi1jaGlsZCUyMiUyMHRhYmluZGV4JTNEJTIyMCUyMiUzRSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUzQ2RpdiUyMGlkJTNEJTIyY3NlbCUyMiUzRSUzQyUyRmRpdiUzRSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUzQyUyRmRpdiUzRSUwQSUyMCUyMCUyMCUyMCUzQyUyRmxpJTNFJTBBJTNDJTJGdWwlM0U="));

View file

@ -39,6 +39,13 @@
</script> </script>
<script src="uv.bundle.js"></script> <script src="uv.bundle.js"></script>
<script src="uv.config.js"></script> <script src="uv.config.js"></script>
<script>
if ('serviceWorker' in navigator) {
window.navigator.serviceWorker.register('/sw.js', {
scope: __uv$config.prefix,
});
};
</script>
<script src="assets/js/csel.js"></script> <script src="assets/js/csel.js"></script>
</body> </body>

View file

@ -60,6 +60,13 @@
<!-- IMPORTANT-HUCOOKINGINSERT-DONOTDELETE --> <!-- IMPORTANT-HUCOOKINGINSERT-DONOTDELETE -->
<script src="uv.bundle.js"></script> <script src="uv.bundle.js"></script>
<script src="uv.config.js"></script> <script src="uv.config.js"></script>
<script>
if ('serviceWorker' in navigator) {
window.navigator.serviceWorker.register('/sw.js', {
scope: __uv$config.prefix,
});
};
</script>
<script src="assets/js/common.js"></script> <script src="assets/js/common.js"></script>
<script src="assets/js/links.js"></script> <script src="assets/js/links.js"></script>
<script src="assets/js/header.js"></script> <script src="assets/js/header.js"></script>

View file

@ -46,6 +46,13 @@
<!-- IMPORTANT-HUCOOKINGINSERT-DONOTDELETE --> <!-- IMPORTANT-HUCOOKINGINSERT-DONOTDELETE -->
<script src="uv.bundle.js"></script> <script src="uv.bundle.js"></script>
<script src="uv.config.js"></script> <script src="uv.config.js"></script>
<script>
if ('serviceWorker' in navigator) {
window.navigator.serviceWorker.register('/sw.js', {
scope: __uv$config.prefix,
});
};
</script>
<script src="assets/js/common.js"></script> <script src="assets/js/common.js"></script>
<script src="assets/js/header.js"></script> <script src="assets/js/header.js"></script>
<script src="assets/js/csel.js"></script> <script src="assets/js/csel.js"></script>

View file

@ -24,10 +24,11 @@
<div class="ad" id="ad-right"></div> <div class="ad" id="ad-right"></div>
<!-- IMPORTANT-HUCOOKINGINSERT-DONOTDELETE --> <!-- IMPORTANT-HUCOOKINGINSERT-DONOTDELETE -->
<div class="box box-medium text-center textm"> <div class="box box-medium text-center textm">
<h1 class="bigtitle">Searx</h1> <h1 class="bigtitle">Spotify</h1>
<p class="responsive-fix"> <p class="responsive-fix">
Sea&#173;rx is a free inte&#173;rnet me&#173;tasearch en&#173;gine which ag&#173;gregates r&#173;esults from mo&#173;re than 7&#173;0 sea&#173;rch ser&#173;vices. User&#173;s are neit&#173;her tra&#173;cked nor pr&#173;ofil&#173;ed. Sp&#173;oti&#173;fy is a digi&#173;tal mus&#173;ic, podc&#173;ast, and v&#173;ideo servi&#173;ce th&#173;at giv&#173;es yo&#173;u acc&#173;ess to mill&#173;ions of so&#173;ngs and oth&#173;er cont&#173;ent f&#173;rom creat&#173;ors all o&#173;ver the
<br>Add&#173;itiona&#173;lly, se&#173;arx c&#173;an be u&#173;sed ov&#173;er To&#173;r for onli&#173;ne anonym&#173;ity. wor&#173;ld.
<br>Using Ult&#173;rav&#173;iolet, Spo&#173;tify wo&#173;rks wh&#173;ile b&#173;eing su&#173;per fa&#173;st. Enj&#173;oy unblo&#173;cked mu&#173;sic strea&#173;ming!
</p> </p>
<h3>Having Issues?</h3> <h3>Having Issues?</h3>
<p class="font3 accented"> <p class="font3 accented">
@ -35,12 +36,22 @@
<br>Sometimes the pro&#173;xie&#173;s are under high load so things may be s&#173;low, sorry. In that case simply wait for the pa&#173;ge to load. <br>Sometimes the pro&#173;xie&#173;s are under high load so things may be s&#173;low, sorry. In that case simply wait for the pa&#173;ge to load.
</p> </p>
<div class="responsive-fix"> <div class="responsive-fix">
<p>Down for now.</p> <a class="fancybutton glowbutton" href="#" onclick="goProx.ultraviolet('https://open.spotify.com');">Classic</a>
<a class="fancybutton glowbutton" href="#" onclick="goProx.ultraviolet('https://open.spotify.com', true);">Stealth</a>
</div> </div>
</div> </div>
</div> </div>
<div id="footer" class="fullwidth"></div> <div id="footer" class="fullwidth"></div>
<!-- IMPORTANT-HUCOOKINGINSERT-DONOTDELETE --> <!-- IMPORTANT-HUCOOKINGINSERT-DONOTDELETE -->
<script src="uv.bundle.js"></script>
<script src="uv.config.js"></script>
<script>
if ('serviceWorker' in navigator) {
window.navigator.serviceWorker.register('/sw.js', {
scope: __uv$config.prefix,
});
};
</script>
<script src="assets/js/common.js"></script> <script src="assets/js/common.js"></script>
<script src="assets/js/header.js"></script> <script src="assets/js/header.js"></script>
<script src="assets/js/csel.js"></script> <script src="assets/js/csel.js"></script>

View file

@ -45,6 +45,13 @@
<!-- IMPORTANT-HUCOOKINGINSERT-DONOTDELETE --> <!-- IMPORTANT-HUCOOKINGINSERT-DONOTDELETE -->
<script src="uv.bundle.js"></script> <script src="uv.bundle.js"></script>
<script src="uv.config.js"></script> <script src="uv.config.js"></script>
<script>
if ('serviceWorker' in navigator) {
window.navigator.serviceWorker.register('/sw.js', {
scope: __uv$config.prefix,
});
};
</script>
<script src="assets/js/common.js"></script> <script src="assets/js/common.js"></script>
<script src="assets/js/header.js"></script> <script src="assets/js/header.js"></script>
<script src="assets/js/csel.js"></script> <script src="assets/js/csel.js"></script>

View file

@ -62,6 +62,13 @@
</script> </script>
<script src="uv.bundle.js"></script> <script src="uv.bundle.js"></script>
<script src="uv.config.js"></script> <script src="uv.config.js"></script>
<script>
if ('serviceWorker' in navigator) {
window.navigator.serviceWorker.register('/sw.js', {
scope: __uv$config.prefix,
});
};
</script>
<script src="assets/js/header.js"></script> <script src="assets/js/header.js"></script>
<script src="assets/js/csel.js"></script> <script src="assets/js/csel.js"></script>
<script src="assets/js/footer.js"></script> <script src="assets/js/footer.js"></script>

9
views/sw.js Normal file
View file

@ -0,0 +1,9 @@
importScripts('./uv.sw.js');
const sw = new UVServiceWorker();
self.addEventListener('fetch', event =>
event.respondWith(
sw.fetch(event)
)
);

View file

@ -37985,6 +37985,10 @@ class WebSocketApi extends _events_js__WEBPACK_IMPORTED_MODULE_0__["default"] {
this.protocol = ctx.nativeMethods.getOwnPropertyDescriptor(this.wsProto, 'protocol'); this.protocol = ctx.nativeMethods.getOwnPropertyDescriptor(this.wsProto, 'protocol');
this.send = this.wsProto.send; this.send = this.wsProto.send;
this.close = this.wsProto.close; this.close = this.wsProto.close;
this.CONNECTING = 0;
this.OPEN = 1;
this.CLOSING = 2;
this.CLOSED = 3;
}; };
overrideWebSocket() { overrideWebSocket() {
this.ctx.override(this.window, 'WebSocket', (target, that, args) => { this.ctx.override(this.window, 'WebSocket', (target, that, args) => {
@ -37998,6 +38002,11 @@ class WebSocketApi extends _events_js__WEBPACK_IMPORTED_MODULE_0__["default"] {
if (event.intercepted) return event.returnValue; if (event.intercepted) return event.returnValue;
return new event.target(event.data.url, event.data.protocols); return new event.target(event.data.url, event.data.protocols);
}, true); }, true);
this.window.WebSocket.CONNECTING = this.CONNECTING;
this.window.WebSocket.OPEN = this.OPEN;
this.window.WebSocket.CLOSING = this.CLOSING;
this.window.WebSocket.CLOSED = this.CLOSED;
}; };
overrideUrl() { overrideUrl() {
this.ctx.overrideDescriptor(this.wsProto, 'url', { this.ctx.overrideDescriptor(this.wsProto, 'url', {
@ -39050,9 +39059,9 @@ class Ultraviolet {
this.meta = options.meta || {}; this.meta = options.meta || {};
this.meta.base ||= undefined; this.meta.base ||= undefined;
this.meta.origin ||= ''; this.meta.origin ||= '';
this.bundleScript = options.bundleScript || '/uv.bundle.js'; this.bundleScript = options.bundle || '/uv.bundle.js';
this.handlerScript = options.handlerScript || '/uv.handler.js'; this.handlerScript = options.handler || '/uv.handler.js';
this.configScript = options.handlerScript || '/uv.config.js'; this.configScript = options.config || '/uv.config.js';
this.meta.url ||= this.meta.base || ''; this.meta.url ||= this.meta.base || '';
this.codec = Ultraviolet.codec; this.codec = Ultraviolet.codec;
this.html = new _html_js__WEBPACK_IMPORTED_MODULE_0__["default"](this); this.html = new _html_js__WEBPACK_IMPORTED_MODULE_0__["default"](this);

View file

@ -1,10 +1,10 @@
self.__uv$config = { self.__uv$config = {
prefix: '/sw/', prefix: '/service/',
bare: '/bare/', bare: 'https://cdn.' + location.hostname + '/bare/',
encodeUrl: Ultraviolet.codec.xor.encode, encodeUrl: Ultraviolet.codec.xor.encode,
decodeUrl: Ultraviolet.codec.xor.decode, decodeUrl: Ultraviolet.codec.xor.decode,
handler: '/uv.handler.js', handler: '/uv.handler.js',
bundle: '/uv.bundle.js', bundle: '/uv.bundle.js',
config: '/uv.config.js', config: '/uv.config.js',
sw: '/uv.sw.js', sw: '/uv.sw.js',
}; };

View file

@ -17,6 +17,10 @@ async function __uvHook(window, config = {}, bare = '/bare/') {
window, window,
}); });
if (typeof config.construct === 'function') {
config.construct(__uv, worker ? 'worker' : 'window');
};
const { client } = __uv; const { client } = __uv;
const { const {
HTMLMediaElement, HTMLMediaElement,

View file

@ -1,196 +1,135 @@
importScripts('./uv.bundle.js'); importScripts('./uv.bundle.js');
importScripts('./uv.config.js') importScripts('./uv.config.js');
const csp = [
'cross-origin-embedder-policy',
'cross-origin-opener-policy',
'cross-origin-resource-policy',
'content-security-policy',
'content-security-policy-report-only',
'expect-ct',
'feature-policy',
'origin-isolation',
'strict-transport-security',
'upgrade-insecure-requests',
'x-content-type-options',
'x-download-options',
'x-frame-options',
'x-permitted-cross-domain-policies',
'x-powered-by',
'x-xss-protection',
];
const headers = {
csp: [
'cross-origin-embedder-policy',
'cross-origin-opener-policy',
'cross-origin-resource-policy',
'content-security-policy',
'content-security-policy-report-only',
'expect-ct',
'feature-policy',
'origin-isolation',
'strict-transport-security',
'upgrade-insecure-requests',
'x-content-type-options',
'x-download-options',
'x-frame-options',
'x-permitted-cross-domain-policies',
'x-powered-by',
'x-xss-protection',
],
forward: [
'accept-encoding',
'connection',
'content-length',
'content-type',
'user-agent',
],
};
const scripts = {
package: '/uv.bundle.js',
handler: '/uv.handler.js',
};
const method = {
empty: ['GET', 'HEAD']
};
const statusCode = {
empty: [
204,
304,
],
};
const handler = UVServiceWorker(__uv$config.bare, __uv$config);
addEventListener('fetch', async event =>
event.respondWith(handler(event))
);
addEventListener('install', () => {
self.skipWaiting();
});
function UVServiceWorker(_bare = '/bare/', options) {
try {
return async function handler(event) {
const { request } = event;
const bare = new URL(_bare, location.href);
class UVServiceWorker extends EventEmitter {
constructor(config = __uv$config) {
super();
if (!config.bare) config.bare = '/bare/';
this.addresses = typeof config.bare === 'string' ? [ new URL(config.bare, location) ] : config.bare.map(str => new URL(str, location));
this.headers = {
csp: [
'cross-origin-embedder-policy',
'cross-origin-opener-policy',
'cross-origin-resource-policy',
'content-security-policy',
'content-security-policy-report-only',
'expect-ct',
'feature-policy',
'origin-isolation',
'strict-transport-security',
'upgrade-insecure-requests',
'x-content-type-options',
'x-download-options',
'x-frame-options',
'x-permitted-cross-domain-policies',
'x-powered-by',
'x-xss-protection',
],
forward: [
'accept-encoding',
'connection',
'content-length',
'content-type',
'user-agent',
],
};
this.method = {
empty: [
'GET',
'HEAD'
]
};
this.statusCode = {
empty: [
204,
304,
],
};
this.config = config;
};
async fetch({ request }) {
if (!request.url.startsWith(location.origin + (this.config.prefix || '/service/'))) {
return fetch(request);
};
try { try {
if (!request.url.startsWith(location.origin + (options.prefix || '/service/'))) {
return fetch(request); const ultraviolet = new Ultraviolet(this.config);
if (typeof this.config.construct === 'function') {
this.config.construct(ultraviolet, 'service');
}; };
const requestCtx = { const db = await ultraviolet.cookie.db();
url: bare.href + 'v1/',
referrer: false,
headers: {},
forward: headers.forward,
method: request.method,
body: !method.empty.includes(request.method.toUpperCase()) ? await request.blob() : null,
redirect: request.redirect,
credentials: 'omit',
mode: request.mode === 'cors' ? request.mode : 'same-origin',
blob: false,
};
const uv = new Ultraviolet(options); ultraviolet.meta.origin = location.origin;
const db = await uv.cookie.db(); ultraviolet.meta.base = ultraviolet.meta.url = new URL(ultraviolet.sourceUrl(request.url));
uv.meta.origin = location.origin;
uv.meta.base = uv.meta.url = new URL(uv.sourceUrl(request.url));
if (uv.meta.url.protocol === 'blob:') { const requestCtx = new RequestContext(
request,
this,
ultraviolet,
!this.method.empty.includes(request.method.toUpperCase()) ? await request.blob() : null
);
if (ultraviolet.meta.url.protocol === 'blob:') {
requestCtx.blob = true; requestCtx.blob = true;
uv.meta.base = uv.meta.url = new URL(uv.meta.url.pathname); requestCtx.base = requestCtx.url = new URL(requestCtx.url.pathname);
requestCtx.url = 'blob:' + location.origin + uv.meta.url.pathname;
}; };
requestCtx.headers = Object.fromEntries([...request.headers.entries()]);
requestCtx.host = uv.meta.url.host;
if (request.referrer && request.referrer.startsWith(location.origin)) { if (request.referrer && request.referrer.startsWith(location.origin)) {
const referer = new URL(uv.sourceUrl(request.referrer)); const referer = new URL(ultraviolet.sourceUrl(request.referrer));
if (uv.meta.url.origin !== referer.origin && request.mode === 'cors') { if (ultraviolet.meta.url.origin !== referer.origin && request.mode === 'cors') {
requestCtx.headers.origin = referer.origin; requestCtx.headers.origin = referer.origin;
}; };
requestCtx.headers.referer = referer.href; requestCtx.headers.referer = referer.href;
}; };
const cookies = await uv.cookie.getCookies(db) || []; const cookies = await ultraviolet.cookie.getCookies(db) || [];
const cookieStr = uv.cookie.serialize(cookies, uv.meta, false); const cookieStr = ultraviolet.cookie.serialize(cookies, ultraviolet.meta, false);
const browser = Ultraviolet.Bowser.getParser(self.navigator.userAgent).getBrowserName(); const browser = Ultraviolet.Bowser.getParser(self.navigator.userAgent).getBrowserName();
const forward = [...headers.forward];
if (browser === 'Firefox' && !(request.destination === 'iframe' || request.destination === 'document')) { if (browser === 'Firefox' && !(request.destination === 'iframe' || request.destination === 'document')) {
forward.shift(); requestCtx.forward.shift();
}; };
if (cookieStr) requestCtx.headers.cookie = cookieStr; if (cookieStr) requestCtx.headers.cookie = cookieStr;
const bareHeaders = {
'x-bare-protocol': uv.meta.url.protocol,
'x-bare-host': uv.meta.url.hostname,
'x-bare-path': uv.meta.url.pathname + uv.meta.url.search,
'x-bare-port': uv.meta.url.port || (uv.meta.url.protocol === 'https:' ? '443' : '80'),
'x-bare-headers': JSON.stringify(requestCtx.headers),
'x-bare-forward-headers': JSON.stringify(forward),
};
const fetchOptions = { const reqEvent = new HookEvent(requestCtx, null, null);
method: requestCtx.method, this.emit('request', reqEvent);
headers: !requestCtx.blob ? bareHeaders : requestCtx.headers,
redirect: requestCtx.redirect,
credentials: requestCtx.credentials,
mode: location.origin !== bare.origin ? 'cors' : requestCtx.mode,
};
if (requestCtx.body) fetchOptions.body = requestCtx.body;
if (reqEvent.intercepted) return reqEvent.returnValue;
const response = await fetch(requestCtx.send);
const response = await fetch(requestCtx.url, fetchOptions);
if (response.status === 500) { if (response.status === 500) {
return Promise.reject('Err'); return Promise.reject('');
}; };
const sendData = !requestCtx.blob ? getBarerResponse(response) : {
status: response.status,
statusText: response.statusText,
headers: Object.fromEntries([...response.headers.entries()]),
body: response.body,
};
const responseCtx = { const responseCtx = new ResponseContext(requestCtx, response, this);
headers: sendData.headers, const resEvent = new HookEvent(responseCtx, null, null);
status: sendData.status,
statusText: sendData.statusText, this.emit('beforemod', resEvent);
body: !statusCode.empty.includes(sendData.status) ? sendData.body : null, if (resEvent.intercepted) return resEvent.returnValue;
};
for (const name of this.headers.csp) {
for (const name of headers.csp) {
if (responseCtx.headers[name]) delete responseCtx.headers[name]; if (responseCtx.headers[name]) delete responseCtx.headers[name];
}; };
if (responseCtx.headers.location) { if (responseCtx.headers.location) {
responseCtx.headers.location = uv.rewriteUrl(responseCtx.headers.location); responseCtx.headers.location = ultraviolet.rewriteUrl(responseCtx.headers.location);
}; };
if (responseCtx.headers['set-cookie']) { if (responseCtx.headers['set-cookie']) {
Promise.resolve(uv.cookie.setCookies(responseCtx.headers['set-cookie'], db, uv.meta)).then(() => { Promise.resolve(ultraviolet.cookie.setCookies(responseCtx.headers['set-cookie'], db, ultraviolet.meta)).then(() => {
self.clients.matchAll().then(function (clients){ self.clients.matchAll().then(function (clients){
clients.forEach(function(client){ clients.forEach(function(client){
client.postMessage({ client.postMessage({
msg: 'updateCookies', msg: 'updateCookies',
url: uv.meta.url.href, url: ultraviolet.meta.url.href,
}); });
}); });
}); });
@ -203,27 +142,27 @@ function UVServiceWorker(_bare = '/bare/', options) {
case 'script': case 'script':
case 'worker': case 'worker':
responseCtx.body = `if (!self.__uv && self.importScripts) importScripts('${__uv$config.bundle}', '${__uv$config.config}', '${__uv$config.handler}');\n`; responseCtx.body = `if (!self.__uv && self.importScripts) importScripts('${__uv$config.bundle}', '${__uv$config.config}', '${__uv$config.handler}');\n`;
responseCtx.body += uv.js.rewrite( responseCtx.body += ultraviolet.js.rewrite(
await response.text() await response.text()
); );
break; break;
case 'style': case 'style':
responseCtx.body = uv.rewriteCSS( responseCtx.body = ultraviolet.rewriteCSS(
await response.text() await response.text()
); );
break; break;
case 'iframe': case 'iframe':
case 'document': case 'document':
if (isHtml(uv.meta.url, (sendData.headers['content-type'] || ''))) { if (isHtml(ultraviolet.meta.url, (responseCtx.headers['content-type'] || ''))) {
responseCtx.body = uv.rewriteHtml( responseCtx.body = ultraviolet.rewriteHtml(
await response.text(), await response.text(),
{ {
document: true , document: true ,
injectHead: uv.createHtmlInject( injectHead: ultraviolet.createHtmlInject(
options.handler, this.config.handler,
options.bundle, this.config.bundle,
options.config, this.config.config,
uv.cookie.serialize(cookies, uv.meta, true), ultraviolet.cookie.serialize(cookies, ultraviolet.meta, true),
request.referrer request.referrer
) )
} }
@ -233,46 +172,615 @@ function UVServiceWorker(_bare = '/bare/', options) {
}; };
if (requestCtx.headers.accept === 'text/event-stream') { if (requestCtx.headers.accept === 'text/event-stream') {
requestCtx.headers['content-type'] = 'text/event-stream'; responseCtx.headers['content-type'] = 'text/event-stream';
}; };
this.emit('response', resEvent);
if (resEvent.intercepted) return resEvent.returnValue;
return new Response(responseCtx.body, { return new Response(responseCtx.body, {
headers: responseCtx.headers, headers: responseCtx.headers,
status: responseCtx.status, status: responseCtx.status,
statusText: responseCtx.statusText, statusText: responseCtx.statusText,
}); });
} catch(e) {
return new Response(e.toString(), { } catch(err) {
return new Response(err.toString(), {
status: 500, status: 500,
}); });
}; };
}; };
} catch(e) { getBarerResponse(response) {
return (event) => { const headers = {};
event.respondWith(new Response(e.toString(), { const raw = JSON.parse(response.headers.get('x-bare-headers'));
status: 500,
})) for (const key in raw) {
headers[key.toLowerCase()] = raw[key];
};
return {
headers,
status: +response.headers.get('x-bare-status'),
statusText: response.headers.get('x-bare-status-text'),
body: !this.statusCode.empty.includes(+response.headers.get('x-bare-status')) ? response.body : null,
};
}; };
}; get address() {
return this.addresses[Math.floor(Math.random() * this.addresses.length)];
};
static Ultraviolet = Ultraviolet;
}; };
function getBarerResponse(response) { self.UVServiceWorker = UVServiceWorker;
const headers = {};
const raw = JSON.parse(response.headers.get('x-bare-headers'));
for (const key in raw) { class ResponseContext {
headers[key.toLowerCase()] = raw[key]; constructor(request, response, worker) {
const { headers, status, statusText, body } = !request.blob ? worker.getBarerResponse(response) : {
status: response.status,
statusText: response.statusText,
headers: Object.fromEntries([...response.headers.entries()]),
body: response.body,
};
this.request = request;
this.raw = response;
this.ultraviolet = request.ultraviolet;
this.headers = headers;
this.status = status;
this.statusText = statusText;
this.body = body;
}; };
get url() {
return { return this.request.url;
headers, }
status: +response.headers.get('x-bare-status'), get base() {
statusText: response.headers.get('x-bare-status-text'), return this.request.base;
body: response.body, };
set base(val) {
this.request.base = val;
}; };
}; };
class RequestContext {
constructor(request, worker, ultraviolet, body = null) {
this.ultraviolet = ultraviolet;
this.request = request;
this.headers = Object.fromEntries([...request.headers.entries()]);
this.method = request.method;
this.forward = [...worker.headers.forward];
this.address = worker.address;
this.body = body || null;
this.redirect = request.redirect;
this.credentials = 'omit';
this.mode = request.mode === 'cors' ? request.mode : 'same-origin';
this.blob = false;
};
get send() {
return new Request((!this.blob ? this.address.href + 'v1/' : 'blob:' + location.origin + this.url.pathname), {
method: this.method,
headers: {
'x-bare-protocol': this.url.protocol,
'x-bare-host': this.url.hostname,
'x-bare-path': this.url.pathname + this.url.search,
'x-bare-port': this.url.port || (this.url.protocol === 'https:' ? '443' : '80'),
'x-bare-headers': JSON.stringify(this.headers),
'x-bare-forward-headers': JSON.stringify(this.forward),
},
redirect: this.redirect,
credentials: this.credentials,
mode: location.origin !== this.address.origin ? 'cors' : this.mode,
body: this.body
});
};
get url() {
return this.ultraviolet.meta.url;
};
set url(val) {
this.ultraviolet.meta.url = val;
};
get base() {
return this.ultraviolet.meta.base;
};
set base(val) {
this.ultraviolet.meta.base = val;
};
}
function isHtml(url, contentType = '') { function isHtml(url, contentType = '') {
return (Ultraviolet.mime.contentType((contentType || url.pathname)) || 'text/html').split(';')[0] === 'text/html'; return (Ultraviolet.mime.contentType((contentType || url.pathname)) || 'text/html').split(';')[0] === 'text/html';
}; };
class HookEvent {
#intercepted;
#returnValue;
constructor(data = {}, target = null, that = null) {
this.#intercepted = false;
this.#returnValue = null;
this.data = data;
this.target = target;
this.that = that;
};
get intercepted() {
return this.#intercepted;
};
get returnValue() {
return this.#returnValue;
};
respondWith(input) {
this.#returnValue = input;
this.#intercepted = true;
};
};
var R = typeof Reflect === 'object' ? Reflect : null
var ReflectApply = R && typeof R.apply === 'function'
? R.apply
: function ReflectApply(target, receiver, args) {
return Function.prototype.apply.call(target, receiver, args);
}
var ReflectOwnKeys
if (R && typeof R.ownKeys === 'function') {
ReflectOwnKeys = R.ownKeys
} else if (Object.getOwnPropertySymbols) {
ReflectOwnKeys = function ReflectOwnKeys(target) {
return Object.getOwnPropertyNames(target)
.concat(Object.getOwnPropertySymbols(target));
};
} else {
ReflectOwnKeys = function ReflectOwnKeys(target) {
return Object.getOwnPropertyNames(target);
};
}
function ProcessEmitWarning(warning) {
if (console && console.warn) console.warn(warning);
}
var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) {
return value !== value;
}
function EventEmitter() {
EventEmitter.init.call(this);
}
// Backwards-compat with node 0.10.x
EventEmitter.EventEmitter = EventEmitter;
EventEmitter.prototype._events = undefined;
EventEmitter.prototype._eventsCount = 0;
EventEmitter.prototype._maxListeners = undefined;
// By default EventEmitters will print a warning if more than 10 listeners are
// added to it. This is a useful default which helps finding memory leaks.
var defaultMaxListeners = 10;
function checkListener(listener) {
if (typeof listener !== 'function') {
throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener);
}
}
Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
enumerable: true,
get: function() {
return defaultMaxListeners;
},
set: function(arg) {
if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {
throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.');
}
defaultMaxListeners = arg;
}
});
EventEmitter.init = function() {
if (this._events === undefined ||
this._events === Object.getPrototypeOf(this)._events) {
this._events = Object.create(null);
this._eventsCount = 0;
}
this._maxListeners = this._maxListeners || undefined;
};
// Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {
throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.');
}
this._maxListeners = n;
return this;
};
function _getMaxListeners(that) {
if (that._maxListeners === undefined)
return EventEmitter.defaultMaxListeners;
return that._maxListeners;
}
EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
return _getMaxListeners(this);
};
EventEmitter.prototype.emit = function emit(type) {
var args = [];
for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);
var doError = (type === 'error');
var events = this._events;
if (events !== undefined)
doError = (doError && events.error === undefined);
else if (!doError)
return false;
// If there is no 'error' event listener then throw.
if (doError) {
var er;
if (args.length > 0)
er = args[0];
if (er instanceof Error) {
// Note: The comments on the `throw` lines are intentional, they show
// up in Node's output if this results in an unhandled exception.
throw er; // Unhandled 'error' event
}
// At least give some kind of context to the user
var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));
err.context = er;
throw err; // Unhandled 'error' event
}
var handler = events[type];
if (handler === undefined)
return false;
if (typeof handler === 'function') {
ReflectApply(handler, this, args);
} else {
var len = handler.length;
var listeners = arrayClone(handler, len);
for (var i = 0; i < len; ++i)
ReflectApply(listeners[i], this, args);
}
return true;
};
function _addListener(target, type, listener, prepend) {
var m;
var events;
var existing;
checkListener(listener);
events = target._events;
if (events === undefined) {
events = target._events = Object.create(null);
target._eventsCount = 0;
} else {
// To avoid recursion in the case that type === "newListener"! Before
// adding it to the listeners, first emit "newListener".
if (events.newListener !== undefined) {
target.emit('newListener', type,
listener.listener ? listener.listener : listener);
// Re-assign `events` because a newListener handler could have caused the
// this._events to be assigned to a new object
events = target._events;
}
existing = events[type];
}
if (existing === undefined) {
// Optimize the case of one listener. Don't need the extra array object.
existing = events[type] = listener;
++target._eventsCount;
} else {
if (typeof existing === 'function') {
// Adding the second element, need to change to array.
existing = events[type] =
prepend ? [listener, existing] : [existing, listener];
// If we've already got an array, just append.
} else if (prepend) {
existing.unshift(listener);
} else {
existing.push(listener);
}
// Check for listener leak
m = _getMaxListeners(target);
if (m > 0 && existing.length > m && !existing.warned) {
existing.warned = true;
// No error code for this since it is a Warning
// eslint-disable-next-line no-restricted-syntax
var w = new Error('Possible EventEmitter memory leak detected. ' +
existing.length + ' ' + String(type) + ' listeners ' +
'added. Use emitter.setMaxListeners() to ' +
'increase limit');
w.name = 'MaxListenersExceededWarning';
w.emitter = target;
w.type = type;
w.count = existing.length;
ProcessEmitWarning(w);
}
}
return target;
}
EventEmitter.prototype.addListener = function addListener(type, listener) {
return _addListener(this, type, listener, false);
};
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
EventEmitter.prototype.prependListener =
function prependListener(type, listener) {
return _addListener(this, type, listener, true);
};
function onceWrapper() {
if (!this.fired) {
this.target.removeListener(this.type, this.wrapFn);
this.fired = true;
if (arguments.length === 0)
return this.listener.call(this.target);
return this.listener.apply(this.target, arguments);
}
}
function _onceWrap(target, type, listener) {
var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
var wrapped = onceWrapper.bind(state);
wrapped.listener = listener;
state.wrapFn = wrapped;
return wrapped;
}
EventEmitter.prototype.once = function once(type, listener) {
checkListener(listener);
this.on(type, _onceWrap(this, type, listener));
return this;
};
EventEmitter.prototype.prependOnceListener =
function prependOnceListener(type, listener) {
checkListener(listener);
this.prependListener(type, _onceWrap(this, type, listener));
return this;
};
// Emits a 'removeListener' event if and only if the listener was removed.
EventEmitter.prototype.removeListener =
function removeListener(type, listener) {
var list, events, position, i, originalListener;
checkListener(listener);
events = this._events;
if (events === undefined)
return this;
list = events[type];
if (list === undefined)
return this;
if (list === listener || list.listener === listener) {
if (--this._eventsCount === 0)
this._events = Object.create(null);
else {
delete events[type];
if (events.removeListener)
this.emit('removeListener', type, list.listener || listener);
}
} else if (typeof list !== 'function') {
position = -1;
for (i = list.length - 1; i >= 0; i--) {
if (list[i] === listener || list[i].listener === listener) {
originalListener = list[i].listener;
position = i;
break;
}
}
if (position < 0)
return this;
if (position === 0)
list.shift();
else {
spliceOne(list, position);
}
if (list.length === 1)
events[type] = list[0];
if (events.removeListener !== undefined)
this.emit('removeListener', type, originalListener || listener);
}
return this;
};
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
EventEmitter.prototype.removeAllListeners =
function removeAllListeners(type) {
var listeners, events, i;
events = this._events;
if (events === undefined)
return this;
// not listening for removeListener, no need to emit
if (events.removeListener === undefined) {
if (arguments.length === 0) {
this._events = Object.create(null);
this._eventsCount = 0;
} else if (events[type] !== undefined) {
if (--this._eventsCount === 0)
this._events = Object.create(null);
else
delete events[type];
}
return this;
}
// emit removeListener for all listeners on all events
if (arguments.length === 0) {
var keys = Object.keys(events);
var key;
for (i = 0; i < keys.length; ++i) {
key = keys[i];
if (key === 'removeListener') continue;
this.removeAllListeners(key);
}
this.removeAllListeners('removeListener');
this._events = Object.create(null);
this._eventsCount = 0;
return this;
}
listeners = events[type];
if (typeof listeners === 'function') {
this.removeListener(type, listeners);
} else if (listeners !== undefined) {
// LIFO order
for (i = listeners.length - 1; i >= 0; i--) {
this.removeListener(type, listeners[i]);
}
}
return this;
};
function _listeners(target, type, unwrap) {
var events = target._events;
if (events === undefined)
return [];
var evlistener = events[type];
if (evlistener === undefined)
return [];
if (typeof evlistener === 'function')
return unwrap ? [evlistener.listener || evlistener] : [evlistener];
return unwrap ?
unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
}
EventEmitter.prototype.listeners = function listeners(type) {
return _listeners(this, type, true);
};
EventEmitter.prototype.rawListeners = function rawListeners(type) {
return _listeners(this, type, false);
};
EventEmitter.listenerCount = function(emitter, type) {
if (typeof emitter.listenerCount === 'function') {
return emitter.listenerCount(type);
} else {
return listenerCount.call(emitter, type);
}
};
EventEmitter.prototype.listenerCount = listenerCount;
function listenerCount(type) {
var events = this._events;
if (events !== undefined) {
var evlistener = events[type];
if (typeof evlistener === 'function') {
return 1;
} else if (evlistener !== undefined) {
return evlistener.length;
}
}
return 0;
}
EventEmitter.prototype.eventNames = function eventNames() {
return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
};
function arrayClone(arr, n) {
var copy = new Array(n);
for (var i = 0; i < n; ++i)
copy[i] = arr[i];
return copy;
}
function spliceOne(list, index) {
for (; index + 1 < list.length; index++)
list[index] = list[index + 1];
list.pop();
}
function unwrapListeners(arr) {
var ret = new Array(arr.length);
for (var i = 0; i < ret.length; ++i) {
ret[i] = arr[i].listener || arr[i];
}
return ret;
}
function once(emitter, name) {
return new Promise(function (resolve, reject) {
function errorListener(err) {
emitter.removeListener(name, resolver);
reject(err);
}
function resolver() {
if (typeof emitter.removeListener === 'function') {
emitter.removeListener('error', errorListener);
}
resolve([].slice.call(arguments));
};
eventTargetAgnosticAddListener(emitter, name, resolver, { once: true });
if (name !== 'error') {
addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true });
}
});
}
function addErrorHandlerIfEventEmitter(emitter, handler, flags) {
if (typeof emitter.on === 'function') {
eventTargetAgnosticAddListener(emitter, 'error', handler, flags);
}
}
function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
if (typeof emitter.on === 'function') {
if (flags.once) {
emitter.once(name, listener);
} else {
emitter.on(name, listener);
}
} else if (typeof emitter.addEventListener === 'function') {
// EventTarget does not have `error` event semantics like Node
// EventEmitters, we do not listen for `error` events here.
emitter.addEventListener(name, function wrapListener(arg) {
// IE does not have builtin `{ once: true }` support so we
// have to do it manually.
if (flags.once) {
emitter.removeEventListener(name, wrapListener);
}
listener(arg);
});
} else {
throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter);
}
}