Path: blob/master/views/uv/uv.handler.js
5227 views
/* -----------------------------------------------1/* Authors: Titanium Network2/* GNU Affero General Public License v3.0: https://www.gnu.org/licenses/agpl-3.0.en.html3/* Modified by Yoct to remove __uv$config.4/* Ultraviolet Handler Script5/* ----------------------------------------------- */67/**8* @type {import('../uv').UltravioletCtor}9*/10const Ultraviolet = self.Ultraviolet;1112/**13* @type {import('../uv').UVClientCtor}14*/15const UVClient = self.UVClient;1617/**18* @type {import('../uv').UVConfig}19*/20const __uv$config = self['{{__uv$config}}'];2122/**23* @type {string}24*/25const __uv$cookies = self.__uv$cookies;2627if (typeof __uv$cookies !== 'string')28throw new TypeError('Unable to load global UV data');2930if (!self.__uv) __uvHook(self);3132self.__uvHook = __uvHook;3334/**35*36* @param {typeof globalThis} window37* @returns38*/39function __uvHook(window) {40if ('__uv' in window && window.__uv instanceof Ultraviolet) return false;4142if (window.document && !!window.window) {43window.document44.querySelectorAll('script[__uv-script]')45.forEach((node) => node.remove());46}4748const worker = !window.window;49const master = '__uv';50const methodPrefix = '__uv$';51const __uv = new Ultraviolet(__uv$config);5253/*if (typeof config.construct === 'function') {54config.construct(__uv, worker ? 'worker' : 'window');55}*/56let bareClient;57if (!worker) {58// websockets59bareClient = new Ultraviolet.BareClient();60} else {61bareClient = new Ultraviolet.BareClient(62new Promise((resolve) => {63addEventListener('message', ({ data }) => {64if (typeof data !== 'object') return;65if ('__uv$type' in data && data.__uv$type === 'baremuxinit') {66resolve(data.port);67}68});69})70);71}7273const client = new UVClient(window, bareClient, worker);74const {75HTMLMediaElement,76HTMLScriptElement,77HTMLAudioElement,78HTMLVideoElement,79HTMLInputElement,80HTMLEmbedElement,81HTMLTrackElement,82HTMLAnchorElement,83HTMLIFrameElement,84HTMLAreaElement,85HTMLLinkElement,86HTMLBaseElement,87HTMLFormElement,88HTMLImageElement,89HTMLSourceElement,90} = window;9192client.nativeMethods.defineProperty(window, '__uv', {93value: __uv,94enumerable: false,95});9697__uv.meta.origin = location.origin;98__uv.location = client.location.emulate(99(href) => {100if (href === 'about:srcdoc') return new URL(href);101if (href.startsWith('blob:')) href = href.slice('blob:'.length);102return new URL(__uv.sourceUrl(href));103},104(href) => {105return __uv.rewriteUrl(href);106}107);108109let cookieStr = __uv$cookies;110111__uv.meta.url = __uv.location;112__uv.domain = __uv.meta.url.host;113__uv.blobUrls = new window.Map();114__uv.referrer = '';115__uv.cookies = [];116__uv.localStorageObj = {};117__uv.sessionStorageObj = {};118119if (__uv.location.href === 'about:srcdoc') {120__uv.meta = window.parent.__uv.meta;121}122123if (window.EventTarget) {124__uv.addEventListener = window.EventTarget.prototype.addEventListener;125__uv.removeListener = window.EventTarget.prototype.removeListener;126__uv.dispatchEvent = window.EventTarget.prototype.dispatchEvent;127}128129// Storage wrappers130client.nativeMethods.defineProperty(131client.storage.storeProto,132'__uv$storageObj',133{134get() {135if (this === client.storage.sessionStorage)136return __uv.sessionStorageObj;137if (this === client.storage.localStorage) return __uv.localStorageObj;138},139enumerable: false,140}141);142143if (window.localStorage) {144for (const key in window.localStorage) {145if (key.startsWith(methodPrefix + __uv.location.origin + '@')) {146__uv.localStorageObj[147key.slice((methodPrefix + __uv.location.origin + '@').length)148] = window.localStorage.getItem(key);149}150}151152__uv.lsWrap = client.storage.emulate(153client.storage.localStorage,154__uv.localStorageObj155);156}157158if (window.sessionStorage) {159for (const key in window.sessionStorage) {160if (key.startsWith(methodPrefix + __uv.location.origin + '@')) {161__uv.sessionStorageObj[162key.slice((methodPrefix + __uv.location.origin + '@').length)163] = window.sessionStorage.getItem(key);164}165}166167__uv.ssWrap = client.storage.emulate(168client.storage.sessionStorage,169__uv.sessionStorageObj170);171}172173let rawBase = window.document174? client.node.baseURI.get.call(window.document)175: window.location.href;176let base = __uv.sourceUrl(rawBase);177178client.nativeMethods.defineProperty(__uv.meta, 'base', {179get() {180if (!window.document) return __uv.meta.url.href;181182if (client.node.baseURI.get.call(window.document) !== rawBase) {183rawBase = client.node.baseURI.get.call(window.document);184base = __uv.sourceUrl(rawBase);185}186187return base;188},189});190191__uv.methods = {192setSource: methodPrefix + 'setSource',193source: methodPrefix + 'source',194location: methodPrefix + 'location',195function: methodPrefix + 'function',196string: methodPrefix + 'string',197eval: methodPrefix + 'eval',198parent: methodPrefix + 'parent',199top: methodPrefix + 'top',200};201202__uv.filterKeys = [203master,204__uv.methods.setSource,205__uv.methods.source,206__uv.methods.location,207__uv.methods.function,208__uv.methods.string,209__uv.methods.eval,210__uv.methods.parent,211__uv.methods.top,212methodPrefix + 'protocol',213methodPrefix + 'storageObj',214methodPrefix + 'url',215methodPrefix + 'modifiedStyle',216methodPrefix + 'config',217methodPrefix + 'dispatched',218'Ultraviolet',219'__uvHook',220];221222client.on('wrap', (target, wrapped) => {223client.nativeMethods.defineProperty(224wrapped,225'name',226client.nativeMethods.getOwnPropertyDescriptor(target, 'name')227);228client.nativeMethods.defineProperty(229wrapped,230'length',231client.nativeMethods.getOwnPropertyDescriptor(target, 'length')232);233234client.nativeMethods.defineProperty(wrapped, __uv.methods.string, {235enumerable: false,236value: client.nativeMethods.fnToString.call(target),237});238239client.nativeMethods.defineProperty(wrapped, __uv.methods.function, {240enumerable: false,241value: target,242});243});244245client.fetch.on('request', (event) => {246event.data.input = __uv.rewriteUrl(event.data.input);247});248249client.fetch.on('requestUrl', (event) => {250event.data.value = __uv.sourceUrl(event.data.value);251});252253client.fetch.on('responseUrl', (event) => {254event.data.value = __uv.sourceUrl(event.data.value);255});256257// XMLHttpRequest258client.xhr.on('open', (event) => {259event.data.input = __uv.rewriteUrl(event.data.input);260});261262client.xhr.on('responseUrl', (event) => {263event.data.value = __uv.sourceUrl(event.data.value);264});265266// Workers267client.workers.on('worker', (event) => {268event.data.url = __uv.rewriteUrl(event.data.url);269});270271client.workers.on('addModule', (event) => {272event.data.url = __uv.rewriteUrl(event.data.url);273});274275client.workers.on('importScripts', (event) => {276for (const i in event.data.scripts) {277event.data.scripts[i] = __uv.rewriteUrl(event.data.scripts[i]);278}279});280281client.workers.on('postMessage', (event) => {282let to = event.data.origin;283284event.data.origin = '*';285event.data.message = {286__data: event.data.message,287__origin: __uv.meta.url.origin,288__to: to,289};290});291292// Navigator293client.navigator.on('sendBeacon', (event) => {294event.data.url = __uv.rewriteUrl(event.data.url);295});296297// Cookies298client.document.on('getCookie', (event) => {299event.data.value = cookieStr;300});301302client.document.on('setCookie', (event) => {303__uv.cookie.db().then((db) => {304__uv.cookie.setCookies(event.data.value, db, __uv.meta);305306__uv.cookie.getCookies(db).then((cookies) => {307cookieStr = __uv.cookie.serialize(cookies, __uv.meta, true);308});309});310311const cookie = __uv.cookie.setCookie(event.data.value)[0];312313if (!cookie.path) cookie.path = '/';314if (!cookie.domain) cookie.domain = __uv.meta.url.hostname;315316if (__uv.cookie.validateCookie(cookie, __uv.meta, true)) {317if (cookieStr.length) cookieStr += '; ';318cookieStr += `${cookie.name}=${cookie.value}`;319}320321event.respondWith(event.data.value);322});323324// HTML325client.element.on('setInnerHTML', (event) => {326switch (event.that.tagName) {327case 'SCRIPT':328event.data.value = __uv.js.rewrite(event.data.value);329break;330case 'STYLE':331event.data.value = __uv.rewriteCSS(event.data.value);332break;333default:334event.data.value = __uv.rewriteHtml(event.data.value);335}336});337338client.element.on('getInnerHTML', (event) => {339switch (event.that.tagName) {340case 'SCRIPT':341event.data.value = __uv.js.source(event.data.value);342break;343default:344event.data.value = __uv.sourceHtml(event.data.value);345}346});347348client.element.on('setOuterHTML', (event) => {349event.data.value = __uv.rewriteHtml(event.data.value, {350document: event.that.tagName === 'HTML',351});352});353354client.element.on('getOuterHTML', (event) => {355switch (event.that.tagName) {356case 'HEAD':357event.data.value = __uv358.sourceHtml(359event.data.value.replace(360/<head(.*)>(.*)<\/head>/s,361'<op-head$1>$2</op-head>'362)363)364.replace(/<op-head(.*)>(.*)<\/op-head>/s, '<head$1>$2</head>');365break;366case 'BODY':367event.data.value = __uv368.sourceHtml(369event.data.value.replace(370/<body(.*)>(.*)<\/body>/s,371'<op-body$1>$2</op-body>'372)373)374.replace(/<op-body(.*)>(.*)<\/op-body>/s, '<body$1>$2</body>');375break;376default:377event.data.value = __uv.sourceHtml(event.data.value, {378document: event.that.tagName === 'HTML',379});380break;381}382383//event.data.value = __uv.sourceHtml(event.data.value, { document: event.that.tagName === 'HTML' });384});385386client.document.on('write', (event) => {387if (!event.data.html.length) return false;388event.data.html = [__uv.rewriteHtml(event.data.html.join(''))];389});390391client.document.on('writeln', (event) => {392if (!event.data.html.length) return false;393event.data.html = [__uv.rewriteHtml(event.data.html.join(''))];394});395396client.element.on('insertAdjacentHTML', (event) => {397event.data.html = __uv.rewriteHtml(event.data.html);398});399400// EventSource401402client.eventSource.on('construct', (event) => {403event.data.url = __uv.rewriteUrl(event.data.url);404});405406client.eventSource.on('url', (event) => {407event.data.url = __uv.rewriteUrl(event.data.url);408});409410// IDB411client.idb.on('idbFactoryOpen', (event) => {412// Don't modify the Ultraviolet cookie database413if (event.data.name === '__op') return;414event.data.name = `${__uv.meta.url.origin}@${event.data.name}`;415});416417client.idb.on('idbFactoryName', (event) => {418event.data.value = event.data.value.slice(419__uv.meta.url.origin.length + 1 /*the @*/420);421});422423// History424client.history.on('replaceState', (event) => {425if (event.data.url)426event.data.url = __uv.rewriteUrl(427event.data.url,428'__uv' in event.that ? event.that.__uv.meta : __uv.meta429);430});431client.history.on('pushState', (event) => {432if (event.data.url)433event.data.url = __uv.rewriteUrl(434event.data.url,435'__uv' in event.that ? event.that.__uv.meta : __uv.meta436);437});438439// Element get set attribute methods440client.element.on('getAttribute', (event) => {441if (442client.element.hasAttribute.call(443event.that,444__uv.attributePrefix + '-attr-' + event.data.name445)446) {447event.respondWith(448event.target.call(449event.that,450__uv.attributePrefix + '-attr-' + event.data.name451)452);453}454});455456// Message457client.message.on('postMessage', (event) => {458let to = event.data.origin;459let call = __uv.call;460461if (event.that) {462call = event.that.__uv$source.call;463}464465event.data.origin = '*';466event.data.message = {467__data: event.data.message,468__origin: (event.that || event.target).__uv$source.location.origin,469__to: to,470};471472event.respondWith(473worker474? call(475event.target,476[event.data.message, event.data.transfer],477event.that478)479: call(480event.target,481[event.data.message, event.data.origin, event.data.transfer],482event.that483)484);485});486487client.message.on('data', (event) => {488const { value: data } = event.data;489if (typeof data === 'object' && '__data' in data && '__origin' in data) {490event.respondWith(data.__data);491}492});493494client.message.on('origin', (event) => {495const data = client.message.messageData.get.call(event.that);496if (typeof data === 'object' && data.__data && data.__origin) {497event.respondWith(data.__origin);498}499});500501client.overrideDescriptor(window, 'origin', {502get: () => {503return __uv.location.origin;504},505});506507client.node.on('baseURI', (event) => {508if (event.data.value.startsWith(window.location.origin))509event.data.value = __uv.sourceUrl(event.data.value);510});511512client.element.on('setAttribute', (event) => {513if (514event.that instanceof HTMLMediaElement &&515event.data.name === 'src' &&516event.data.value.startsWith('blob:')517) {518event.target.call(519event.that,520__uv.attributePrefix + '-attr-' + event.data.name,521event.data.value522);523event.data.value = __uv.blobUrls.get(event.data.value);524return;525}526527if (__uv.attrs.isUrl(event.data.name)) {528event.target.call(529event.that,530__uv.attributePrefix + '-attr-' + event.data.name,531event.data.value532);533event.data.value = __uv.rewriteUrl(event.data.value);534}535536if (__uv.attrs.isStyle(event.data.name)) {537event.target.call(538event.that,539__uv.attributePrefix + '-attr-' + event.data.name,540event.data.value541);542event.data.value = __uv.rewriteCSS(event.data.value, {543context: 'declarationList',544});545}546547if (__uv.attrs.isHtml(event.data.name)) {548event.target.call(549event.that,550__uv.attributePrefix + '-attr-' + event.data.name,551event.data.value552);553event.data.value = __uv.rewriteHtml(event.data.value, {554...__uv.meta,555document: true,556injectHead: __uv.createHtmlInject(557__uv.handlerScript,558__uv.bundleScript,559__uv.clientScript,560__uv.configScript,561cookieStr,562window.location.href563),564});565}566567if (__uv.attrs.isSrcset(event.data.name)) {568event.target.call(569event.that,570__uv.attributePrefix + '-attr-' + event.data.name,571event.data.value572);573event.data.value = __uv.html.wrapSrcset(event.data.value.toString());574}575576if (__uv.attrs.isForbidden(event.data.name)) {577event.data.name = __uv.attributePrefix + '-attr-' + event.data.name;578}579});580581client.element.on('audio', (event) => {582event.data.url = __uv.rewriteUrl(event.data.url);583});584585// Element Property Attributes586client.element.hookProperty(587[HTMLAnchorElement, HTMLAreaElement, HTMLLinkElement, HTMLBaseElement],588'href',589{590get: (target, that) => {591return __uv.sourceUrl(target.call(that));592},593set: (target, that, [val]) => {594client.element.setAttribute.call(595that,596__uv.attributePrefix + '-attr-href',597val598);599target.call(that, __uv.rewriteUrl(val));600},601}602);603604client.element.hookProperty(605[606HTMLScriptElement,607HTMLAudioElement,608HTMLVideoElement,609HTMLMediaElement,610HTMLImageElement,611HTMLInputElement,612HTMLEmbedElement,613HTMLIFrameElement,614HTMLTrackElement,615HTMLSourceElement,616],617'src',618{619get: (target, that) => {620return __uv.sourceUrl(target.call(that));621},622set: (target, that, [val]) => {623if (624new String(val).toString().trim().startsWith('blob:') &&625that instanceof HTMLMediaElement626) {627client.element.setAttribute.call(628that,629__uv.attributePrefix + '-attr-src',630val631);632return target.call(that, __uv.blobUrls.get(val) || val);633}634635client.element.setAttribute.call(636that,637__uv.attributePrefix + '-attr-src',638val639);640target.call(that, __uv.rewriteUrl(val));641},642}643);644645client.element.hookProperty([HTMLFormElement], 'action', {646get: (target, that) => {647return __uv.sourceUrl(target.call(that));648},649set: (target, that, [val]) => {650client.element.setAttribute.call(651that,652__uv.attributePrefix + '-attr-action',653val654);655target.call(that, __uv.rewriteUrl(val));656},657});658659client.element.hookProperty([HTMLImageElement], 'srcset', {660get: (target, that) => {661return (662client.element.getAttribute.call(663that,664__uv.attributePrefix + '-attr-srcset'665) || target.call(that)666);667},668set: (target, that, [val]) => {669client.element.setAttribute.call(670that,671__uv.attributePrefix + '-attr-srcset',672val673);674target.call(that, __uv.html.wrapSrcset(val.toString()));675},676});677678client.element.hookProperty(HTMLScriptElement, 'integrity', {679get: (target, that) => {680return client.element.getAttribute.call(681that,682__uv.attributePrefix + '-attr-integrity'683);684},685set: (target, that, [val]) => {686client.element.setAttribute.call(687that,688__uv.attributePrefix + '-attr-integrity',689val690);691},692});693694client.element.hookProperty(HTMLIFrameElement, 'sandbox', {695get: (target, that) => {696return (697client.element.getAttribute.call(698that,699__uv.attributePrefix + '-attr-sandbox'700) || target.call(that)701);702},703set: (target, that, [val]) => {704client.element.setAttribute.call(705that,706__uv.attributePrefix + '-attr-sandbox',707val708);709},710});711712// HTMLIFrameElement may not be defined (workers)713const contentWindowGet =714HTMLIFrameElement &&715Object.getOwnPropertyDescriptor(716HTMLIFrameElement.prototype,717'contentWindow'718).get;719720function uvInject(that) {721const win = contentWindowGet.call(that);722723if (!win.__uv)724try {725__uvHook(win);726} catch (e) {727console.error('catastrophic failure');728console.error(e);729}730}731732client.element.hookProperty(HTMLIFrameElement, 'contentWindow', {733get: (target, that) => {734uvInject(that);735return target.call(that);736},737});738739client.element.hookProperty(HTMLIFrameElement, 'contentDocument', {740get: (target, that) => {741uvInject(that);742return target.call(that);743},744});745746client.element.hookProperty(HTMLIFrameElement, 'srcdoc', {747get: (target, that) => {748return (749client.element.getAttribute.call(750that,751__uv.attributePrefix + '-attr-srcdoc'752) || target.call(that)753);754},755set: (target, that, [val]) => {756target.call(757that,758__uv.rewriteHtml(val, {759document: true,760injectHead: __uv.createHtmlInject(761__uv.handlerScript,762__uv.bundleScript,763__uv.clientScript,764__uv.configScript,765cookieStr,766window.location.href767),768})769);770},771});772773client.node.on('getTextContent', (event) => {774if (event.that.tagName === 'SCRIPT') {775event.data.value = __uv.js.source(event.data.value);776}777});778779client.node.on('setTextContent', (event) => {780if (event.that.tagName === 'SCRIPT') {781event.data.value = __uv.js.rewrite(event.data.value);782}783});784785// Until proper rewriting is implemented for service workers.786// Not sure atm how to implement it with the already built in service worker787if ('serviceWorker' in window.navigator) {788delete window.Navigator.prototype.serviceWorker;789}790791// Document792client.document.on('getDomain', (event) => {793event.data.value = __uv.domain;794});795client.document.on('setDomain', (event) => {796if (797!event.data.value798.toString()799.endsWith(__uv.meta.url.hostname.split('.').slice(-2).join('.'))800)801return event.respondWith('');802event.respondWith((__uv.domain = event.data.value));803});804805client.document.on('url', (event) => {806event.data.value = __uv.location.href;807});808809client.document.on('documentURI', (event) => {810event.data.value = __uv.location.href;811});812813client.document.on('referrer', (event) => {814event.data.value = __uv.referrer || __uv.sourceUrl(event.data.value);815});816817client.document.on('parseFromString', (event) => {818if (event.data.type !== 'text/html') return false;819event.data.string = __uv.rewriteHtml(event.data.string, {820...__uv.meta,821document: true,822});823});824825// Attribute (node.attributes)826client.attribute.on('getValue', (event) => {827if (828client.element.hasAttribute.call(829event.that.ownerElement,830__uv.attributePrefix + '-attr-' + event.data.name831)832) {833event.data.value = client.element.getAttribute.call(834event.that.ownerElement,835__uv.attributePrefix + '-attr-' + event.data.name836);837}838});839840client.attribute.on('setValue', (event) => {841if (__uv.attrs.isUrl(event.data.name)) {842client.element.setAttribute.call(843event.that.ownerElement,844__uv.attributePrefix + '-attr-' + event.data.name,845event.data.value846);847event.data.value = __uv.rewriteUrl(event.data.value);848}849850if (__uv.attrs.isStyle(event.data.name)) {851client.element.setAttribute.call(852event.that.ownerElement,853__uv.attributePrefix + '-attr-' + event.data.name,854event.data.value855);856event.data.value = __uv.rewriteCSS(event.data.value, {857context: 'declarationList',858});859}860861if (__uv.attrs.isHtml(event.data.name)) {862client.element.setAttribute.call(863event.that.ownerElement,864__uv.attributePrefix + '-attr-' + event.data.name,865event.data.value866);867event.data.value = __uv.rewriteHtml(event.data.value, {868...__uv.meta,869document: true,870injectHead: __uv.createHtmlInject(871__uv.handlerScript,872__uv.bundleScript,873__uv.clientScript,874__uv.configScript,875cookieStr,876window.location.href877),878});879}880881if (__uv.attrs.isSrcset(event.data.name)) {882client.element.setAttribute.call(883event.that.ownerElement,884__uv.attributePrefix + '-attr-' + event.data.name,885event.data.value886);887event.data.value = __uv.html.wrapSrcset(event.data.value.toString());888}889});890891// URL892client.url.on('createObjectURL', (event) => {893let url = event.target.call(event.that, event.data.object);894if (url.startsWith('blob:' + location.origin)) {895let newUrl =896'blob:' +897(__uv.meta.url.href !== 'about:blank'898? __uv.meta.url.origin899: window.parent.__uv.meta.url.origin) +900url.slice('blob:'.length + location.origin.length);901__uv.blobUrls.set(newUrl, url);902event.respondWith(newUrl);903} else {904event.respondWith(url);905}906});907908client.url.on('revokeObjectURL', (event) => {909if (__uv.blobUrls.has(event.data.url)) {910const old = event.data.url;911event.data.url = __uv.blobUrls.get(event.data.url);912__uv.blobUrls.delete(old);913}914});915916client.storage.on('get', (event) => {917event.data.name =918methodPrefix + __uv.meta.url.origin + '@' + event.data.name;919});920921client.storage.on('set', (event) => {922if (event.that.__uv$storageObj) {923event.that.__uv$storageObj[event.data.name] = event.data.value;924}925event.data.name =926methodPrefix + __uv.meta.url.origin + '@' + event.data.name;927});928929client.storage.on('delete', (event) => {930if (event.that.__uv$storageObj) {931delete event.that.__uv$storageObj[event.data.name];932}933event.data.name =934methodPrefix + __uv.meta.url.origin + '@' + event.data.name;935});936937client.storage.on('getItem', (event) => {938event.data.name =939methodPrefix + __uv.meta.url.origin + '@' + event.data.name;940});941942client.storage.on('setItem', (event) => {943if (event.that.__uv$storageObj) {944event.that.__uv$storageObj[event.data.name] = event.data.value;945}946event.data.name =947methodPrefix + __uv.meta.url.origin + '@' + event.data.name;948});949950client.storage.on('removeItem', (event) => {951if (event.that.__uv$storageObj) {952delete event.that.__uv$storageObj[event.data.name];953}954event.data.name =955methodPrefix + __uv.meta.url.origin + '@' + event.data.name;956});957958client.storage.on('clear', (event) => {959if (event.that.__uv$storageObj) {960for (const key of client.nativeMethods.keys.call(961null,962event.that.__uv$storageObj963)) {964delete event.that.__uv$storageObj[key];965client.storage.removeItem.call(966event.that,967methodPrefix + __uv.meta.url.origin + '@' + key968);969event.respondWith();970}971}972});973974client.storage.on('length', (event) => {975if (event.that.__uv$storageObj) {976event.respondWith(977client.nativeMethods.keys.call(null, event.that.__uv$storageObj).length978);979}980});981982client.storage.on('key', (event) => {983if (event.that.__uv$storageObj) {984event.respondWith(985client.nativeMethods.keys.call(null, event.that.__uv$storageObj)[986event.data.index987] || null988);989}990});991992client.function.on('function', (event) => {993event.data.script = __uv.rewriteJS(event.data.script);994});995996client.function.on('toString', (event) => {997if (__uv.methods.string in event.that)998event.respondWith(event.that[__uv.methods.string]);999});10001001client.object.on('getOwnPropertyNames', (event) => {1002event.data.names = event.data.names.filter(1003(element) => !__uv.filterKeys.includes(element)1004);1005});10061007client.object.on('getOwnPropertyDescriptors', (event) => {1008for (const forbidden of __uv.filterKeys) {1009delete event.data.descriptors[forbidden];1010}1011});10121013client.style.on('setProperty', (event) => {1014if (client.style.dashedUrlProps.includes(event.data.property)) {1015event.data.value = __uv.rewriteCSS(event.data.value, {1016context: 'value',1017...__uv.meta,1018});1019}1020});10211022client.style.on('getPropertyValue', (event) => {1023if (client.style.dashedUrlProps.includes(event.data.property)) {1024event.respondWith(1025__uv.sourceCSS(event.target.call(event.that, event.data.property), {1026context: 'value',1027...__uv.meta,1028})1029);1030}1031});10321033if ('CSS2Properties' in window) {1034for (const key of client.style.urlProps) {1035client.overrideDescriptor(window.CSS2Properties.prototype, key, {1036get: (target, that) => {1037return __uv.sourceCSS(target.call(that), {1038context: 'value',1039...__uv.meta,1040});1041},1042set: (target, that, val) => {1043target.call(1044that,1045__uv.rewriteCSS(val, {1046context: 'value',1047...__uv.meta,1048})1049);1050},1051});1052}1053} else if ('HTMLElement' in window) {1054client.overrideDescriptor(window.HTMLElement.prototype, 'style', {1055get: (target, that) => {1056const value = target.call(that);1057if (!value[methodPrefix + 'modifiedStyle']) {1058for (const key of client.style.urlProps) {1059client.nativeMethods.defineProperty(value, key, {1060enumerable: true,1061configurable: true,1062get() {1063const value =1064client.style.getPropertyValue.call(this, key) || '';1065return __uv.sourceCSS(value, {1066context: 'value',1067...__uv.meta,1068});1069},1070set(val) {1071client.style.setProperty.call(1072this,1073client.style.propToDashed[key] || key,1074__uv.rewriteCSS(val, {1075context: 'value',1076...__uv.meta,1077})1078);1079},1080});1081client.nativeMethods.defineProperty(1082value,1083methodPrefix + 'modifiedStyle',1084{1085enumerable: false,1086value: true,1087}1088);1089}1090}1091return value;1092},1093});1094}10951096client.style.on('setCssText', (event) => {1097event.data.value = __uv.rewriteCSS(event.data.value, {1098context: 'declarationList',1099...__uv.meta,1100});1101});11021103client.style.on('getCssText', (event) => {1104event.data.value = __uv.sourceCSS(event.data.value, {1105context: 'declarationList',1106...__uv.meta,1107});1108});11091110// Proper hash emulation.1111__uv.addEventListener.call(window, 'hashchange', (event) => {1112if (event.__uv$dispatched) return false;1113event.stopImmediatePropagation();1114const hash = window.location.hash;1115client.history.replaceState.call(window.history, '', '', event.oldURL);1116__uv.location.hash = hash;1117});11181119client.location.on('hashchange', (oldUrl, newUrl, ctx) => {1120if (ctx.HashChangeEvent && client.history.replaceState) {1121client.history.replaceState.call(1122window.history,1123'',1124'',1125__uv.rewriteUrl(newUrl)1126);11271128const event = new ctx.HashChangeEvent('hashchange', {1129newURL: newUrl,1130oldURL: oldUrl,1131});11321133client.nativeMethods.defineProperty(event, methodPrefix + 'dispatched', {1134value: true,1135enumerable: false,1136});11371138__uv.dispatchEvent.call(window, event);1139}1140});11411142// Hooking functions & descriptors1143client.fetch.overrideRequest();1144client.fetch.overrideUrl();1145client.xhr.overrideOpen();1146client.xhr.overrideResponseUrl();1147client.element.overrideHtml();1148client.element.overrideAttribute();1149client.element.overrideInsertAdjacentHTML();1150client.element.overrideAudio();1151// client.element.overrideQuerySelector();1152client.node.overrideBaseURI();1153client.node.overrideTextContent();1154client.attribute.overrideNameValue();1155client.document.overrideDomain();1156client.document.overrideURL();1157client.document.overrideDocumentURI();1158client.document.overrideWrite();1159client.document.overrideReferrer();1160client.document.overrideParseFromString();1161client.storage.overrideMethods();1162client.storage.overrideLength();1163//client.document.overrideQuerySelector();1164client.object.overrideGetPropertyNames();1165client.object.overrideGetOwnPropertyDescriptors();1166client.idb.overrideName();1167client.idb.overrideOpen();1168client.history.overridePushState();1169client.history.overrideReplaceState();1170client.eventSource.overrideConstruct();1171client.eventSource.overrideUrl();1172client.websocket.overrideWebSocket(bareClient);1173client.url.overrideObjectURL();1174client.document.overrideCookie();1175client.message.overridePostMessage();1176client.message.overrideMessageOrigin();1177client.message.overrideMessageData();1178client.workers.overrideWorker();1179client.workers.overrideAddModule();1180client.workers.overrideImportScripts();1181client.workers.overridePostMessage();1182client.style.overrideSetGetProperty();1183client.style.overrideCssText();1184client.navigator.overrideSendBeacon();1185client.function.overrideFunction();1186client.function.overrideToString();1187client.location.overrideWorkerLocation((href) => {1188return new URL(__uv.sourceUrl(href));1189});11901191client.overrideDescriptor(window, 'localStorage', {1192get: (target, that) => {1193return (that || window).__uv.lsWrap;1194},1195});1196client.overrideDescriptor(window, 'sessionStorage', {1197get: (target, that) => {1198return (that || window).__uv.ssWrap;1199},1200});12011202client.override(window, 'open', (target, that, args) => {1203if (!args.length) return target.apply(that, args);1204let [url] = args;12051206url = __uv.rewriteUrl(url);12071208return target.call(that, url);1209});12101211__uv.$wrap = function (name) {1212if (name === 'location') return __uv.methods.location;1213if (name === 'eval') return __uv.methods.eval;1214return name;1215};12161217__uv.$get = function (that) {1218if (that === window.location) return __uv.location;1219if (that === window.eval) return __uv.eval;1220if (that === window.parent) {1221return window.__uv$parent;1222}1223if (that === window.top) {1224return window.__uv$top;1225}1226return that;1227};12281229__uv.eval = client.wrap(window, 'eval', (target, that, args) => {1230if (!args.length || typeof args[0] !== 'string')1231return target.apply(that, args);1232let [script] = args;12331234script = __uv.rewriteJS(script);1235return target.call(that, script);1236});12371238__uv.call = function (target, args, that) {1239return that ? target.apply(that, args) : target(...args);1240};12411242__uv.call$ = function (obj, prop, args = []) {1243return obj[prop].apply(obj, args);1244};12451246client.nativeMethods.defineProperty(window.Object.prototype, master, {1247get: () => {1248return __uv;1249},1250enumerable: false,1251});12521253client.nativeMethods.defineProperty(1254window.Object.prototype,1255__uv.methods.setSource,1256{1257value: function (source) {1258if (!client.nativeMethods.isExtensible(this)) return this;12591260client.nativeMethods.defineProperty(this, __uv.methods.source, {1261value: source,1262writable: true,1263enumerable: false,1264});12651266return this;1267},1268enumerable: false,1269}1270);12711272client.nativeMethods.defineProperty(1273window.Object.prototype,1274__uv.methods.source,1275{1276value: __uv,1277writable: true,1278enumerable: false,1279}1280);12811282client.nativeMethods.defineProperty(1283window.Object.prototype,1284__uv.methods.location,1285{1286configurable: true,1287get() {1288return this === window.document || this === window1289? __uv.location1290: this.location;1291},1292set(val) {1293if (this === window.document || this === window) {1294__uv.location.href = val;1295} else {1296this.location = val;1297}1298},1299}1300);13011302client.nativeMethods.defineProperty(1303window.Object.prototype,1304__uv.methods.parent,1305{1306configurable: true,1307get() {1308const val = this.parent;13091310if (this === window) {1311try {1312return '__uv' in val ? val : this;1313} catch (e) {1314return this;1315}1316}1317return val;1318},1319set(val) {1320this.parent = val;1321},1322}1323);13241325client.nativeMethods.defineProperty(1326window.Object.prototype,1327__uv.methods.top,1328{1329configurable: true,1330get() {1331const val = this.top;13321333if (this === window) {1334if (val === this.parent) return this[__uv.methods.parent];1335try {1336if (!('__uv' in val)) {1337let current = this;13381339while (current.parent !== val) {1340current = current.parent;1341}13421343return '__uv' in current ? current : this;1344} else {1345return val;1346}1347} catch (e) {1348return this;1349}1350}1351return val;1352},1353set(val) {1354this.top = val;1355},1356}1357);13581359client.nativeMethods.defineProperty(1360window.Object.prototype,1361__uv.methods.eval,1362{1363configurable: true,1364get() {1365return this === window ? __uv.eval : this.eval;1366},1367set(val) {1368this.eval = val;1369},1370}1371);1372}137313741375