This commit is contained in:
Jason 2022-02-19 00:10:57 -05:00
parent 82f5f76588
commit 2c06fed426
25 changed files with 1131 additions and 604 deletions

View file

@ -3,7 +3,7 @@ import path from "path";
const __dirname = path.resolve(path.dirname(decodeURI(new URL(import.meta.url).pathname))).slice(3);
console.log(__dirname);
console.log(path.resolve(path.dirname(decodeURI(new URL(import.meta.url).pathname))), __dirname);
webpack({
mode: 'none',

View file

@ -15,6 +15,7 @@ import NavigatorApi from "./navigator.js";
import Workers from "./worker.js";
import URLApi from "./url.js";
import EventEmitter from "./events.js";
import StorageApi from "./storage.js";
class UVClient extends EventEmitter {
constructor(window = self, worker = !window.window) {
@ -25,9 +26,14 @@ class UVClient extends EventEmitter {
defineProperty: this.window.Object.defineProperty,
getOwnPropertyDescriptor: this.window.Object.getOwnPropertyDescriptor,
getOwnPropertyDescriptors: this.window.Object.getOwnPropertyDescriptors,
getOwnPropertyNames: this.window.Object.getOwnPropertyNames,
keys: this.window.Object.keys,
getOwnPropertySymbols: this.window.Object.getOwnPropertySymbols,
isArray: this.window.Array.isArray,
setPrototypeOf: this.window.Object.setPrototypeOf,
isExtensible: this.window.Object.isExtensible,
Map: this.window.Map,
Proxy: this.window.Proxy,
};
this.worker = worker;
this.fetch = new Fetch(this);
@ -46,6 +52,7 @@ class UVClient extends EventEmitter {
this.url = new URLApi(this);
this.workers = new Workers(this);
this.location = new LocationApi(this);
this.storage = new StorageApi(this);
};
initLocation(rewriteUrl, sourceUrl) {
this.location = new LocationApi(this, sourceUrl, rewriteUrl, this.worker);

View file

@ -95,6 +95,18 @@ class LocationApi {
});
};
if ('ancestorOrigins' in this.location) {
this.ctx.nativeMethods.defineProperty(emulation, 'ancestorOrigins', {
get() {
const arr = [];
if (that.window.DOMStringList) that.ctx.nativeMethods.setPrototypeOf(arr, that.window.DOMStringList.prototype);
return arr;
},
set: undefined,
enumerable: true,
});
};
this.ctx.nativeMethods.defineProperty(emulation, 'toString', {
value: this.ctx.wrap(this.location, 'toString', () => {

155
client/storage.js Normal file
View file

@ -0,0 +1,155 @@
import EventEmitter from "./events.js";
import HookEvent from "./hook.js";
class StorageApi extends EventEmitter {
constructor(ctx) {
super();
this.ctx = ctx;
this.window = ctx.window;
this.localStorage = this.window.localStorage || null;
this.sessionStorage = this.window.sessionStorage || null;
this.Storage = this.window.Storage || {};
this.storeProto = this.Storage.prototype || {};
this.getItem = this.storeProto.getItem || null;
this.setItem = this.storeProto.setItem || null;
this.removeItem = this.storeProto.removeItem || null;
this.clear = this.storeProto.clear || null;
this.key = this.storeProto.key || null;
this.methods = ['key', 'getItem', 'setItem', 'removeItem', 'clear'];
this.wrappers = new ctx.nativeMethods.Map();
};
overrideMethods() {
this.ctx.override(this.storeProto, 'getItem', (target, that, args) => {
if (!args.length) return target.apply((this.wrappers.get(that) || that), args);
let [ name ] = args;
const event = new HookEvent({ name }, target, (this.wrappers.get(that) || that));
this.emit('getItem', event);
if (event.intercepted) return event.returnValue;
return event.target.call(event.that, event.data.name);
});
this.ctx.override(this.storeProto, 'setItem', (target, that, args) => {
if (2 > args.length) return target.apply((this.wrappers.get(that) || that), args);
let [ name, value ] = args;
const event = new HookEvent({ name, value }, target, (this.wrappers.get(that) || that));
this.emit('setItem', event);
if (event.intercepted) return event.returnValue;
return event.target.call(event.that, event.data.name, event.data.value);
});
this.ctx.override(this.storeProto, 'removeItem', (target, that, args) => {
if (!args.length) return target.apply((this.wrappers.get(that) || that), args);
let [ name ] = args;
const event = new HookEvent({ name }, target, (this.wrappers.get(that) || that));
this.emit('removeItem', event);
if (event.intercepted) return event.returnValue;
return event.target.call(event.that, event.data.name);
});
this.ctx.override(this.storeProto, 'clear', (target, that) => {
const event = new HookEvent(null, target, (this.wrappers.get(that) || that));
this.emit('clear', event);
if (event.intercepted) return event.returnValue;
return event.target.call(event.that);
});
this.ctx.override(this.storeProto, 'key', (target, that, args) => {
if (!args.length) return target.apply((this.wrappers.get(that) || that), args);
let [ index ] = args;
const event = new HookEvent({ index }, target, (this.wrappers.get(that) || that));
this.emit('key', event);
if (event.intercepted) return event.returnValue;
return event.target.call(event.that, event.data.index);
});
};
overrideLength() {
this.ctx.overrideDescriptor(this.storeProto, 'length', {
get: (target, that) => {
const event = new HookEvent({ length: target.call((this.wrappers.get(that) || that)) }, target, (this.wrappers.get(that) || that));
this.emit('length', event);
if (event.intercepted) return event.returnValue;
return event.data.length;
},
});
};
emulate(storage, obj = {}) {
this.ctx.nativeMethods.setPrototypeOf(obj, this.storeProto);
const proxy = new this.ctx.window.Proxy(obj, {
get: (target, prop) => {
if (prop in this.storeProto || typeof prop === 'symbol') return storage[prop];
const event = new HookEvent({ name: prop }, null, storage);
this.emit('get', event);
if (event.intercepted) return event.returnValue;
return storage[event.data.name];
},
set: (target, prop, value) => {
if (prop in this.storeProto || typeof prop === 'symbol') return storage[prop] = value;
const event = new HookEvent({ name: prop, value }, null, storage);
this.emit('set', event);
if (event.intercepted) return event.returnValue;
return storage[event.data.name] = event.data.value;
},
deleteProperty: (target, prop) => {
if (typeof prop === 'symbol') return delete storage[prop];
const event = new HookEvent({ name: prop }, null, storage);
this.emit('delete', event);
if (event.intercepted) return event.returnValue;
return delete storage[event.data.name];
},
});
this.wrappers.set(proxy, storage);
this.ctx.nativeMethods.setPrototypeOf(proxy, this.storeProto);
return proxy;
};
};
export default StorageApi;
class StorageWrapper {
constructor(api, storage, wrap, unwrap, origin) {
this.api = api;
this.ctx = api.ctx;
this.storage = storage;
this.wrap = wrap;
this.unwrap = unwrap;
this.origin = origin;
this.emulation = {};
};
clear() {
for (const key in this.storage) {
const data = this.unwrap(key);
if (!data || data.origin !== this.origin) continue;
this.api.removeItem.call(this.storage, key);
};
this.emulation = {};
this.ctx.nativeMethods.setPrototypeOf(this.emulation, this.api.storeProto);
};
__init() {
for (const key in this.storage) {
const data = this.unwrap(key);
if (!data || data.origin !== this.origin) continue;
this.emulation[data.name] = this.api.getItem.call(this.storage, key);
};
this.ctx.nativeMethods.setPrototypeOf(this.emulation, this.api.storeProto);
};
};

View file

@ -1,4 +1,4 @@
{
"prefix": "/service/",
"prefix": "/sw/",
"bare": "/bare/"
}

View file

@ -5,7 +5,7 @@
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/uv.sw.js', {
scope: '/service/'
scope: '/sw/'
});
navigator.serviceWorker.ready.then(() => {
location.reload()

View file

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<style>
html, body {
margin: 0;
padding: 0;
}
iframe {
position: absolute;
width: 100%;
height: 100%;
border: none;
}
</style>
</head>
<body>
<iframe src="https://localhost/sw/hvtrs8%2F-wuw%2Cgmoelg.aoo%2F"></iframe>
</body>
</html>

View file

@ -14,4 +14,4 @@
addEventListener('message', e => console.log(e.source.postMessage !== window.postMessage));
</script>
</body>
</html>__uv$get(frame, 'postMessage', __uv)
</html>

View file

@ -18,7 +18,7 @@ console.log(
*/
console.log(
uv.rewriteJS('window.eval(saasdsd)')
uv.rewriteJS('top')
)
/*

File diff suppressed because one or more lines are too long

View file

@ -1,3 +1,11 @@
if (!self.__uv) {
__uvHook(self, {
prefix: '/sw/',
encodeUrl: Ultraviolet.codec.xor.encode,
decodeUrl: Ultraviolet.codec.xor.decode,
});
};
async function __uvHook(window, config = {}) {
if ('__uv' in window && window.__uv instanceof Ultraviolet) return false;
@ -37,6 +45,7 @@ async function __uvHook(window, config = {}) {
__uv.meta.origin = location.origin;
__uv.location = client.location.emulate(
(href) => {
if (href === 'about:srcdoc') return new URL(href);
if (href.startsWith('blob:')) href = href.slice('blob:'.length);
return new URL(__uv.sourceUrl(href));
},
@ -51,6 +60,44 @@ async function __uvHook(window, config = {}) {
__uv.blobUrls = new window.Map();
__uv.referrer = '';
__uv.cookies = [];
__uv.localStorageObj = {};
__uv.sessionStorageObj = {};
if (__uv.location.href === 'about:srcdoc') {
__uv.meta = window.parent.__uv.meta;
};
// Storage wrappers
client.nativeMethods.defineProperty(client.storage.storeProto, '__uv$storageObj', {
get() {
if (this === client.storage.sessionStorage) return __uv.sessionStorageObj;
if (this === client.storage.localStorage) return __uv.localStorageObj;
},
enumerable: false,
});
if (window.localStorage) {
for (const key in window.localStorage) {
if (key.startsWith(methodPrefix + __uv.location.origin + '@')) {
__uv.localStorageObj[key.slice((methodPrefix + __uv.location.origin + '@').length)] = window.localStorage.getItem(key);
};
};
__uv.lsWrap = client.storage.emulate(client.storage.localStorage, __uv.localStorageObj);
};
if (window.sessionStorage) {
for (const key in window.sessionStorage) {
if (key.startsWith(methodPrefix + __uv.location.origin + '@')) {
__uv.sessionStorageObj[key.slice((methodPrefix + __uv.location.origin + '@').length)] = window.sessionStorage.getItem(key);
};
};
__uv.ssWrap = client.storage.emulate(client.storage.sessionStorage, __uv.sessionStorageObj);
};
let rawBase = window.document ? client.node.baseURI.get.call(window.document) : window.location.href;
let base = __uv.sourceUrl(rawBase);
@ -76,6 +123,8 @@ async function __uvHook(window, config = {}) {
function: methodPrefix + 'function',
string: methodPrefix + 'string',
eval: methodPrefix + 'eval',
parent: methodPrefix + 'parent',
top: methodPrefix + 'top',
};
__uv.filterKeys = [
@ -86,6 +135,9 @@ async function __uvHook(window, config = {}) {
__uv.methods.function,
__uv.methods.string,
__uv.methods.eval,
__uv.methods.parent,
__uv.methods.top,
methodPrefix + 'storageObj',
'Ultraviolet',
'__uvHook',
];
@ -343,7 +395,12 @@ async function __uvHook(window, config = {}) {
if (__uv.attrs.isHtml(event.data.name)) {
event.target.call(event.that, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value);
event.data.value = __uv.rewriteHtml(event.data.value, { ...__uv.meta, document: true });
event.data.value = __uv.rewriteHtml(event.data.value, {...__uv.meta, document: true, injectHead: __uv.createHtmlInject(__uv.handlerScript, __uv.bundleScript, __uv.cookieStr, window.location.href) });
};
if (__uv.attrs.isSrcset(event.data.name)) {
event.target.call(event.that, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value);
event.data.value = __uv.html.wrapSrcset(event.data.value);
};
if (__uv.attrs.isForbidden(event.data.name)) {
@ -397,6 +454,16 @@ async function __uvHook(window, config = {}) {
},
});
client.element.hookProperty([HTMLImageElement], 'srcset', {
get: (target, that) => {
return client.element.getAttribute.call(that, __uv.attributePrefix + '-attr-srcset') || target.call(that);
},
set: (target, that, [val]) => {
client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-srcset', val)
target.call(that, __uv.html.wrapSrcset(val));
},
});
client.element.hookProperty(HTMLScriptElement, 'integrity', {
get: (target, that) => {
return client.element.getAttribute.call(that, __uv.attributePrefix + '-attr-integrity');
@ -419,7 +486,7 @@ async function __uvHook(window, config = {}) {
get: (target, that) => {
const win = target.call(that);
try {
if (!win.__uv) __uvHook(win);
if (!win.__uv) __uvHook(win, config);
return win;
} catch (e) {
return win;
@ -432,7 +499,7 @@ async function __uvHook(window, config = {}) {
const doc = target.call(that);
try {
const win = doc.defaultView
if (!win.__uv) __uvHook(win);
if (!win.__uv) __uvHook(win, config);
return doc;
} catch (e) {
return win;
@ -440,6 +507,18 @@ async function __uvHook(window, config = {}) {
},
});
client.element.hookProperty(HTMLIFrameElement, 'srcdoc', {
get: (target, that) => {
return client.element.getAttribute.call(that, __uv.attributePrefix + '-attr-srcdoc') || target.call(that);
},
set: (target, that, [val]) => {
target.call(that, __uv.rewriteHtml(val, {
document: true,
injectHead: __uv.createHtmlInject(__uv.handlerScript, __uv.bundleScript, __uv.cookieStr, window.location.href)
}))
},
});
client.node.on('getTextContent', event => {
if (event.that.tagName === 'SCRIPT') {
event.data.value = __uv.js.source(event.data.value);
@ -498,17 +577,14 @@ async function __uvHook(window, config = {}) {
if (__uv.attrs.isHtml(event.data.name)) {
client.element.setAttribute.call(event.that.ownerElement, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value);
event.data.value = __uv.rewriteHtml(event.data.value, { ...__uv.meta, document: true });
event.data.value = __uv.rewriteHtml(event.data.value, {...__uv.meta, document: true, injectHead: __uv.createHtmlInject(__uv.handlerScript, __uv.bundleScript, __uv.cookieStr, window.location.href) });
};
});
client.override(window.JSON, 'stringify', (target, that, args) => {
try {
return target.apply(that, args);
} catch (e) {
console.log(e, 'Error', args);
if (__uv.attrs.isSrcset(event.data.name)) {
client.element.setAttribute.call(event.that.ownerElement, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value);
event.data.value = __uv.html.wrapSrcset(event.data.value);
};
});
// URL
@ -532,6 +608,70 @@ async function __uvHook(window, config = {}) {
};
});
client.storage.on('refresh', event => {
});
client.storage.on('get', event => {
event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name;
});
client.storage.on('set', event => {
if (event.that.__uv$storageObj) {
event.that.__uv$storageObj[event.data.name] = event.data.value;
};
event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name;
});
client.storage.on('delete', event => {
if (event.that.__uv$storageObj) {
delete event.that.__uv$storageObj[event.data.name];
};
event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name;
});
client.storage.on('getItem', event => {
event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name;
});
client.storage.on('setItem', event => {
if (event.that.__uv$storageObj) {
event.that.__uv$storageObj[event.data.name] = event.data.value;
};
event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name;
});
client.storage.on('removeItem', event => {
if (event.that.__uv$storageObj) {
delete event.that.__uv$storageObj[event.data.name];
};
event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name;
});
client.storage.on('clear', event => {
if (event.that.__uv$storageObj) {
for (const key of client.nativeMethods.keys.call(null, event.that.__uv$storageObj)) {
delete event.that.__uv$storageObj[key];
client.storage.removeItem.call(event.that, methodPrefix + __uv.meta.url.origin + '@' + key);
event.respondWith();
};
};
});
client.storage.on('length', event => {
if (event.that.__uv$storageObj) {
event.respondWith(client.nativeMethods.keys.call(null, event.that.__uv$storageObj).length);
};
});
client.storage.on('key', event => {
if (event.that.__uv$storageObj) {
event.respondWith(
(client.nativeMethods.keys.call(null, event.that.__uv$storageObj)[event.data.index] || null)
);
};
});
client.websocket.on('websocket', event => {
const url = new URL(event.data.url);
@ -590,8 +730,6 @@ async function __uvHook(window, config = {}) {
});
client.object.on('getOwnPropertyDescriptors', event => {
console.log(event.data.descriptors);
for (const forbidden of __uv.filterKeys) {
delete event.data.descriptors[forbidden];
};
@ -617,6 +755,8 @@ async function __uvHook(window, config = {}) {
client.document.overrideWrite();
client.document.overrideReferrer();
client.document.overrideParseFromString();
client.storage.overrideMethods();
client.storage.overrideLength();
//client.document.overrideQuerySelector();
client.object.overrideGetPropertyNames();
client.object.overrideGetOwnPropertyDescriptors();
@ -643,20 +783,34 @@ async function __uvHook(window, config = {}) {
(href) => {
return new URL(__uv.sourceUrl(href));
}
)
);
client.nativeMethods.defineProperty(__uv, '$wrap', {
get() {
return function(name) {
client.overrideDescriptor(window, 'localStorage', {
get: (target, that) => {
return (that || window).__uv.lsWrap;
},
});
client.overrideDescriptor(window, 'sessionStorage', {
get: (target, that) => {
return (that || window).__uv.ssWrap;
},
});
client.override(window, 'open', (target, that, args) => {
if (!args.length) return target.apply(that, args);
let [url] = args;
url = __uv.rewriteUrl(url);
return target.call(that, url);
});
__uv.$wrap = function(name) {
if (name === 'location') return __uv.methods.location;
if (name === 'eval') return __uv.methods.eval;
return name;
};
},
set: val => {
console.log('waht the fuck', val);
},
});
__uv.$get = function(that) {
@ -690,9 +844,6 @@ async function __uvHook(window, config = {}) {
client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.setSource, {
value: function(source) {
if (!client.nativeMethods.isExtensible(this)) console.log('you suck');
if (!client.nativeMethods.isExtensible(this)) return this;
client.nativeMethods.defineProperty(this, __uv.methods.source, {
@ -715,7 +866,6 @@ async function __uvHook(window, config = {}) {
client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.location, {
configurable: true,
get() {
return (this === window.document || this === window) ? __uv.location : this.location;
},
set(val) {
@ -727,6 +877,57 @@ async function __uvHook(window, config = {}) {
},
});
client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.parent, {
configurable: true,
get() {
const val = this.parent;
if (this === window) {
try {
return '__uv' in val ? val : this;
} catch (e) {
return this;
};
};
return val;
},
set(val) {
this.parent = val;
},
});
client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.top, {
configurable: true,
get() {
const val = this.top;
if (this === window) {
if (val === this.parent) return this[__uv.methods.parent];
try {
if (!('__uv' in val)) {
let current = this;
while (current.parent !== val) {
current = current.parent
};
return '__uv' in current ? current : this;
} else {
return val;
};
} catch (e) {
return this;
};
};
return val;
},
set(val) {
this.top = val;
},
});
client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.eval, {
configurable: true,
get() {
@ -737,7 +938,3 @@ async function __uvHook(window, config = {}) {
},
});
};
if (!self.__uv) {
__uvHook(self, {});
};

View file

@ -40,7 +40,6 @@ const headers = {
],
forward: [
'accept-encoding',
'accept',
'connection',
'content-length',
'content-type',
@ -64,7 +63,11 @@ const statusCode = {
],
};
const handler = UVServiceWorker('/bare/v1/', {});
const handler = UVServiceWorker('/bare/v1/', {
prefix: '/sw/',
encodeUrl: Ultraviolet.codec.xor.encode,
decodeUrl: Ultraviolet.codec.xor.decode,
});
addEventListener('fetch',
async event => {
@ -73,6 +76,11 @@ addEventListener('fetch',
},
);
// Immediate activation.
addEventListener('install', () => {
self.skipWaiting();
});
function UVServiceWorker(bare = '/bare/v1/', options) {
try {
@ -103,6 +111,7 @@ function UVServiceWorker(bare = '/bare/v1/', options) {
uv.meta.origin = location.origin;
uv.meta.base = uv.meta.url = new URL(uv.sourceUrl(request.url));
/*
uv.html.on('element', (element, type) => {
if (type !== 'rewrite') return false;
if (element.tagName !== 'head') return false;
@ -144,6 +153,7 @@ function UVServiceWorker(bare = '/bare/v1/', options) {
}
);
});
*/
if (uv.meta.url.protocol === 'blob:') {
requestCtx.blob = true;
@ -153,6 +163,8 @@ function UVServiceWorker(bare = '/bare/v1/', options) {
requestCtx.headers = Object.fromEntries([...request.headers.entries()]);
requestCtx.host = uv.meta.url.host;
if (request.referrer && request.referrer.startsWith(location.origin)) {
const referer = new URL(uv.sourceUrl(request.referrer));
@ -165,6 +177,14 @@ function UVServiceWorker(bare = '/bare/v1/', options) {
const cookies = await uv.cookie.getCookies(db) || [];
const cookieStr = uv.cookie.serialize(cookies, uv.meta, false);
const browser = Ultraviolet.Bowser.getParser(self.navigator.userAgent).getBrowserName();
const forward = [...headers.forward];
if (browser === 'Firefox' && !(request.destination === 'iframe' || request.destination === 'document')) {
forward.shift();
};
if (cookieStr) requestCtx.headers.cookie = cookieStr;
const bareHeaders = {
@ -173,7 +193,7 @@ function UVServiceWorker(bare = '/bare/v1/', options) {
'x-bare-path': uv.meta.url.pathname + uv.meta.url.search,
'x-bare-port': uv.meta.url.port,
'x-bare-headers': JSON.stringify(requestCtx.headers),
'x-bare-forward-headers': JSON.stringify(requestCtx.forward),
'x-bare-forward-headers': JSON.stringify(forward),
};
const fetchOptions = {
@ -185,7 +205,9 @@ function UVServiceWorker(bare = '/bare/v1/', options) {
};
if (requestCtx.body) fetchOptions.body = requestCtx.body;
const response = await fetch(requestCtx.url, fetchOptions);
if (response.status === 500) {
return Promise.reject('Err');
};
@ -252,7 +274,12 @@ function UVServiceWorker(bare = '/bare/v1/', options) {
await response.text(),
{
document: true ,
cookies,
injectHead: uv.createHtmlInject(
scripts.handler,
scripts.package,
uv.cookie.serialize(cookies, uv.meta, true),
request.referrer
)
}
);
};
@ -269,14 +296,12 @@ function UVServiceWorker(bare = '/bare/v1/', options) {
statusText: responseCtx.statusText,
});
} catch(e) {
console.log(e);
return new Response(e.toString(), {
status: 500,
});
};
};
} catch(e) {
console.log(e);
return (event) => {
event.respondWith(new Response(e.toString(), {
status: 500,

11
package-lock.json generated
View file

@ -9,6 +9,7 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"bowser": "^2.11.0",
"css-tree": "^2.0.4",
"esotope-hammerhead": "^0.6.1",
"idb": "^7.0.0",
@ -333,6 +334,11 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"node_modules/bowser": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
"integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA=="
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -1908,6 +1914,11 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"bowser": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
"integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA=="
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",

View file

@ -10,6 +10,7 @@
"license": "ISC",
"type": "module",
"dependencies": {
"bowser": "^2.11.0",
"css-tree": "^2.0.4",
"esotope-hammerhead": "^0.6.1",
"idb": "^7.0.0",

View file

@ -36,7 +36,23 @@ async function db(openDB) {
function serialize(cookies = [], meta, js) {
let str = '';
const now = new Date();
for (const cookie of cookies) {
let expired = false;
if (cookie.set) {
if (cookie.maxAge) {
expired = cookie.set.getTime() + (cookie.maxAge * 1e3) < now;
} else if (cookie.expires) {
expired = cookie.expires > now;
};
};
if (expired) {
continue;
};
if (!validateCookie(cookie, meta, js)) continue;
if (str.length) str += '; ';
str += cookie.name;
@ -47,11 +63,30 @@ function serialize(cookies = [], meta, js) {
};
async function getCookies(db) {
return await db.getAll('cookies');
const now = new Date();
return (await db.getAll('cookies')).filter(cookie => {
let expired = false;
if (cookie.set) {
if (cookie.maxAge) {
expired = (cookie.set.getTime() + (cookie.maxAge * 1e3)) < now;
} else if (cookie.expires) {
expired = new Date(cookie.expires.toLocaleString()) < now;
};
};
if (expired) {
db.delete('cookies', cookie.id);
return false;
};
return true;
});
};
function setCookies(data, db, meta) {
if (!db) return false;
const cookies = setCookie(data, {
decodeValues: false,
})
@ -67,6 +102,7 @@ function setCookies(data, db, meta) {
db.put('cookies', {
...cookie,
id: `${cookie.domain}@${cookie.path}@${cookie.name}`,
set: new Date(Date.now()),
});
};
return true;

View file

@ -28,7 +28,6 @@ class CSS extends EventEmitter {
});
return this.generate(ast);
} catch(e) {
console.log(e)
return str;
};
};

View file

@ -5,13 +5,15 @@ import setCookie from 'set-cookie-parser';
import { xor, base64, plain } from './codecs.js';
import mimeTypes from './mime.js';
import { validateCookie, db, getCookies, setCookies, serialize } from './cookie.js';
import { attributes, isUrl, isForbidden, isHtml, isSrcset, isStyle, text } from './rewrite.html.js';
import { attributes, isUrl, isForbidden, isHtml, isSrcset, isStyle, text, injectHead, createInjection } from './rewrite.html.js';
import { importStyle, url } from './rewrite.css.js';
//import { call, destructureDeclaration, dynamicImport, getProperty, importDeclaration, setProperty, sourceMethods, wrapEval, wrapIdentifier } from './rewrite.script.js';
import { dynamicImport, identifier, importDeclaration, property, unwrap, wrapEval } from './rewrite.script.test.js';
import { dynamicImport, identifier, importDeclaration, property, unwrap, wrapEval } from './rewrite.script.js';
import { openDB } from 'idb';
import parsel from './parsel.js';
import UVClient from '../client/index.js';
import Bowser from 'bowser';
const valid_chars = "!#$%&'*+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~";
const reserved_chars = "%";
@ -29,6 +31,8 @@ class Ultraviolet {
this.meta = options.meta || {};
this.meta.base ||= undefined;
this.meta.origin ||= '';
this.bundleScript = options.bundleScript || '/uv.bundle.js';
this.handlerScript = options.handlerScript || '/uv.handler.js';
this.meta.url ||= this.meta.base || '';
this.codec = Ultraviolet.codec;
this.html = new HTML(this);
@ -36,10 +40,12 @@ class Ultraviolet {
this.js = new JS(this);
this.parsel = parsel;
this.openDB = this.constructor.openDB;
this.Bowser = this.constructor.Bowser;
this.client = typeof self !== 'undefined' ? new UVClient((options.window || self)) : null;
this.master = '__uv';
this.dataPrefix = '__uv$';
this.attributePrefix = '__uv';
this.createHtmlInject = createInjection;
this.attrs = {
isUrl,
isForbidden,
@ -133,31 +139,17 @@ class Ultraviolet {
// HTML
attributes(this);
text(this);
injectHead(this);
// CSS
url(this);
importStyle(this);
// JS
/*
getProperty(this);
call(this)
setProperty(this);
sourceMethods(this);
importDeclaration(this);
dynamicImport(this);
wrapEval(this);
wrapIdentifier(this)
*/
importDeclaration(this);
dynamicImport(this);
property(this);
wrapEval(this);
identifier(this);
unwrap(this);
//destructureDeclaration(this)
};
get rewriteHtml() {
return this.html.rewrite.bind(this.html);
@ -181,6 +173,7 @@ class Ultraviolet {
static mime = mimeTypes;
static setCookie = setCookie;
static openDB = openDB;
static Bowser = Bowser;
};
export default Ultraviolet;

View file

@ -90,33 +90,4 @@ class JS extends EventEmitter {
};
};
class NodeEvent extends EventEmitter {
constructor(node, parent = null) {
super();
this._node = node;
for (let key in node) {
Object.defineProperty(this, key, {
get: () => node[key],
sel: val => node[key] = val,
});
};
this.parent = parent;
};
iterate(handler) {
for (const key in this._node) {
if (key === 'parent') continue;
if (Array.isArray(this._node[key])) {
this._node[key].forEach(entry => {
const child = new this.constructor(entry, this._node);
handler(child);
});
} else {
const child = new this.constructor(entry, this._node);
walk(this._node[key], this._node, handler);
};
};
};
};
export default JS;
export { NodeEvent };

View file

@ -1,5 +1,5 @@
function attributes(ctx, meta = ctx.meta) {
const { html, js, css, attributePrefix } = ctx;
const { html, js, css, attributePrefix, handlerScript, bundleScript } = ctx;
const origPrefix = attributePrefix + '-attr-';
html.on('attr', (attr, type) => {
@ -20,7 +20,11 @@ function attributes(ctx, meta = ctx.meta) {
if (type === 'rewrite' && isHtml(attr.name)) {
attr.node.setAttribute(origPrefix + attr.name, attr.value);
attr.value = html.rewrite(attr.value, { ...meta, document: true });
attr.value = html.rewrite(attr.value, {
...meta,
document: true,
injectHead: attr.options.injectHead || [],
});
};
@ -154,6 +158,53 @@ function isEvent(name) {
].indexOf(name) > -1;
};
function injectHead(ctx) {
const { html, js, css, attributePrefix } = ctx;
const origPrefix = attributePrefix + '-attr-';
html.on('element', (element, type) => {
if (type !== 'rewrite') return false;
if (element.tagName !== 'head') return false;
if (!('injectHead' in element.options)) return false;
element.childNodes.unshift(
...element.options.injectHead
);
});
};
function createInjection(handler = '/uv.handler.js', bundle = '/uv.bundle.js', cookies = '', referrer = '') {
return [
{
tagName: 'script',
nodeName: 'script',
childNodes: [
{
nodeName: '#text',
value: `window.__uv$cookies = atob("${btoa(cookies)}");\nwindow.__uv$referrer = atob("${btoa(referrer)}");`
},
],
attrs: [],
skip: true,
},
{
tagName: 'script',
nodeName: 'script',
childNodes: [],
attrs: [
{ name: 'src', value: bundle, skip: true }
],
},
{
tagName: 'script',
nodeName: 'script',
childNodes: [],
attrs: [
{ name: 'src', value: handler, skip: true }
],
},
];
};
function isForbidden(name) {
return ['http-equiv', 'integrity', 'sandbox', 'nonce', 'crossorigin'].indexOf(name) > -1;
};
@ -171,4 +222,4 @@ function isSrcset(name) {
};
export { attributes, text, isUrl, isEvent, isForbidden, isHtml, isStyle, isSrcset };
export { attributes, createInjection, text, isUrl, isEvent, isForbidden, isHtml, isStyle, isSrcset, injectHead };

View file

@ -1,384 +1,92 @@
import { Syntax } from 'esotope-hammerhead';
const master = '__uv';
const methodPrefix = '__uv$';
const uvMethods = {
get: methodPrefix + 'get',
proxy: methodPrefix + 'proxy',
call: methodPrefix + 'call',
set: methodPrefix + 'set',
script: methodPrefix + 'script',
url: methodPrefix + 'url',
object: methodPrefix + 'obj'
};
const uvMethodTypes = {
[methodPrefix + 'get']: 'get',
[methodPrefix + 'proxy']: 'proxy',
[methodPrefix + 'call']: 'call',
[methodPrefix + 'set']: 'set',
[methodPrefix + 'script']: 'script',
[methodPrefix + 'url']: 'url',
[methodPrefix + 'obj']: 'object'
};
const shortHandAssignment = {
'+=': '+',
'-=': '-',
'*=': '*',
'/=': '/',
'%=': '%',
'**=': '**',
'<<=': '<<',
'>>=': '>>',
'>>>=': '>>>',
'&=': '&',
'^=': '^',
'|=': '|',
};
const assignmentOperators = ['=', '+=', '-=', '*=', '/=', '%=', '**=', '<<=', '>>=', '>>>=', '&=', '^=', '|='];
function getProperty(ctx) {
function property(ctx) {
const { js } = ctx;
js.on(Syntax.MemberExpression, (node, data, type) => {
if (type !== 'rewrite') return false;
if (node.object.type === Syntax.Super)
return false;
if (node.parent.type === Syntax.AssignmentExpression && node.parent.left === node)
return false;
if (node.parent.type === Syntax.CallExpression && node.parent.callee === node)
return false;
if (node.parent.type === Syntax.UnaryExpression && node.parent.operator === 'delete')
return false;
if (node.parent.type === Syntax.UpdateExpression && (node.parent.operator === '++' || parent.operator === '--'))
return false;
if (node.parent.type === Syntax.NewExpression && node.parent.callee === node)
return false;
if (node.parent.type === Syntax.ForInStatement && node.parent.left === node) return false;
if (node.computed && node.property.type === Syntax.Literal && !shouldWrapProperty(node.property.value))
return false;
if (!node.computed && node.property.type === Syntax.Identifier && !shouldWrapProperty(node.property.name))
return false;
js.on('MemberExpression', (node, data, type) => {
if (node.object.type === 'Super') return false;
if (type === 'rewrite' && computedProperty(node)) {
data.changes.push({
node: `${uvMethods.get}((`,
start: node.start,
end: node.object.start,
})
node.object.iterateEnd = function () {
data.changes.push({
start: node.object.end,
node: '__uv.$wrap((',
start: node.property.start,
end: node.property.start,
});
data.changes.push({
node: '), ('
});
if (node.computed) {
node.property.iterateEnd = function () {
})
node.iterateEnd = function() {
data.changes.push({
node: '))',
start: node.property.end,
end: node.end,
node: `), ${master}, true)`
end: node.property.end,
});
};
};
if (!node.computed && node.property.name === 'location' && type === 'rewrite' || node.property.name === '__uv$location' && type === 'source') {
data.changes.push({
start: node.property.start,
end: node.property.end,
node: type === 'rewrite' ? '__uv$setSource(__uv).__uv$location' : 'location'
});
};
if (!node.computed && node.property.name === 'top' && type === 'rewrite' || node.property.name === '__uv$top' && type === 'source') {
data.changes.push({
start: node.property.start,
end: node.property.end,
node: type === 'rewrite' ? '__uv$setSource(__uv).__uv$top' : 'top'
});
};
if (!node.computed && node.property.name === 'parent' && type === 'rewrite' || node.property.name === '__uv$parent' && type === 'source') {
data.changes.push({
start: node.property.start,
end: node.property.end,
node: type === 'rewrite' ? '__uv$setSource(__uv).__uv$parent' : 'parent'
});
};
if (!node.computed && node.property.name === 'postMessage' && type === 'rewrite') {
data.changes.push({
start: node.property.start,
end: node.property.end,
node:'__uv$setSource(__uv).postMessage',
});
};
if (!node.computed && node.property.name === 'eval' && type === 'rewrite' || node.property.name === '__uv$eval' && type === 'source') {
data.changes.push({
start: node.property.start,
end: node.property.end,
node: type === 'rewrite' ? '__uv$setSource(__uv).__uv$eval' : 'eval'
});
};
if (!node.computed && node.property.name === '__uv$setSource' && type === 'source' && node.parent.type === Syntax.CallExpression) {
const { parent, property } = node;
data.changes.push({
start: property.start - 1,
end: parent.end,
});
};
} else {
data.changes.push({
end: node.end,
node: '"' + node.property.name + `"), ${master}, false)`
})
};
};
})
};
function call(ctx) {
const { js } = ctx;
js.on(Syntax.CallExpression, (node, data, type) => {
if (type !== 'rewrite') return false;
if (node.callee.type !== Syntax.MemberExpression)
return false;
if (node.callee.object.type === Syntax.Super)
return false;
if (node.callee.computed && node.callee.property.type === Syntax.Literal && !shouldWrapProperty(node.callee.property.value))
return false;
if (!node.callee.computed && node.callee.property.type === Syntax.Identifier && !shouldWrapProperty(node.callee.property.name))
return false;
const { callee } = node;
data.changes.push({
node: `${uvMethods.call}((`,
start: node.start,
end: callee.object.start,
})
callee.object.iterateEnd = function () {
data.changes.push({
start: callee.object.end,
end: callee.property.start,
});
data.changes.push({
node: '), ('
});
if (callee.computed) {
callee.property.iterateEnd = function() {
data.changes.push({
end: node.arguments.length ? node.arguments[0].start : callee.end,
start: callee.property.end,
node: '), ['
})
node.iterateEnd = function() {
data.changes.push({
end: node.end,
start: node.arguments.length ? node.arguments[node.arguments.length - 1].end : callee.end,
node: `], ${master}, true)`
})
start: property.start,
end: parent.end,
});
};
};
} else {
data.changes.push({
end: node.arguments.length ? node.arguments[0].start : false,
node: '"' + callee.property.name + '"), ['
})
node.iterateEnd = function() {
data.changes.push({
end: node.end,
start: node.arguments.length ? node.arguments[node.arguments.length - 1].end : false,
node: `], ${master}, false)`
})
};
};
};
});
};
function setProperty(ctx) {
function identifier(ctx) {
const { js } = ctx;
js.on(Syntax.AssignmentExpression, (node, data, type) => {
if (type !== 'rewrite') return false;
if (node.left.type !== Syntax.MemberExpression) return false;
if (!assignmentOperators.includes(node.operator)) return false;
if (node.left.object.type === Syntax.Super)
return false;
if (node.left.computed && node.left.property.type === Syntax.Literal && !shouldWrapProperty(node.left.property.value))
return false;
if (!node.left.computed && node.left.property.type === Syntax.Identifier && !shouldWrapProperty(node.left.property.name))
return false;
const { left, right } = node;
data.changes.push({
node: `${uvMethods.set}((`,
start: left.object.start,
end: left.object.start,
});
left.object.iterateEnd = function () {
data.changes.push({
start: left.object.end,
end: left.property.start,
});
data.changes.push({
node: '), ('
});
if (left.computed) {
left.property.iterateEnd = function() {
data.changes.push({
end: right.start,
node: '' + left.property.name + '), '
})
if (shortHandAssignment[node.operator]) {
data.changes.push({
node: data.input.slice(left.start, left.end) + ` ${shortHandAssignment[node.operator]} `
})
};
node.iterateEnd = function() {
data.changes.push({
end: node.end,
start: right.end,
node: `, ${master}, true)`
})
};
};
} else {
data.changes.push({
end: right.start,
node: '"' + left.property.name + '"), '
})
if (shortHandAssignment[node.operator]) {
data.changes.push({
node: data.input.slice(left.start, left.end) + ` ${shortHandAssignment[node.operator]} `
})
};
node.iterateEnd = function() {
data.changes.push({
end: node.end,
start: right.end,
node: `, ${master}, false)`
})
};
};
};
});
};
function wrapEval(ctx) {
const { js } = ctx;
js.on(Syntax.CallExpression, (node, data, type) => {
if (type !== 'rewrite') return false;
if (!node.arguments.length) return false;
if (node.callee.type !== Syntax.Identifier) return false;
if (node.callee.name !== 'eval') return false;
const [ script ] = node.arguments;
data.changes.push({
node: uvMethods.script + '(',
start: script.start,
end: script.start,
})
node.iterateEnd = function() {
data.changes.push({
node: ')',
start: script.end,
end: script.end,
});
};
});
};
function sourceMethods(ctx) {
const { js } = ctx;
js.on(Syntax.CallExpression, (node, data, type) => {
if (type !== 'source') return false;
if (node.callee.type !== Syntax.Identifier) return false;
if (!uvMethodTypes[node.callee.name]) return false;
const info = uvWrapperInfo(node, data);
switch(uvMethodTypes[node.callee.name]) {
case 'set':
data.changes.push({
node: info.computed ? `${info.object}[${info.property}] = ${info.value}` : `${info.object}.${info.property} = ${info.value}`,
start: node.start,
end: node.end,
});
break;
case 'get':
data.changes.push({
node: info.computed ? `${info.object}[${info.property}]` : `${info.object}.${info.property}`,
start: node.start,
end: node.end,
});
break;
case 'call':
data.changes.push({
node: info.computed ? `${info.object}[${info.property}](${info.args})` : `${info.object}.${info.property}${info.args}`,
start: node.start,
end: node.end,
});
break;
case 'script':
data.changes.push({
node: info.script,
start: node.start,
end: node.end
});
break;
case 'url':
data.changes.push({
node: info.url,
start: node.start,
end: node.end
});
break;
case 'proxy':
data.changes.push({
node: info.name,
start: node.start,
end: node.end,
});
break;
};
});
};
function uvWrapperInfo(node, { input }) {
const method = uvMethodTypes[node.callee.name];
switch(method) {
case 'set':
{
const [ object, property, value, source, computed ] = node.arguments;
return {
method,
object: input.slice(object.start - 1, object.end + 1),
property: property.type === Syntax.Literal && !computed.value ? property.value : input.slice(property.start, property.end),
computed: !!computed.value,
value: input.slice(value.start, value.end),
};
};
case 'get':
{
const [ object, property, source, computed ] = node.arguments;
return {
method,
object: input.slice(object.start - 1, object.end + 1),
property: property.type === Syntax.Literal && !computed.value ? property.value : input.slice(property.start, property.end),
computed: !!computed.value,
}
};
case 'call':
{
const [ object, property, args, source, computed ] = node.arguments;
return {
method,
object: input.slice(object.start - 1, object.end + 1),
property: property.type === Syntax.Literal && !computed.value ? property.value : input.slice(property.start, property.end),
args: input.slice(args.start + 1, args.end - 1),
computed: !!computed.value,
};
};
case 'script':
{
const [ script ] = node.arguments;
return {
script: input.slice(script.start, script.end),
}
}
case 'url':
{
const [ url ] = node.arguments;
return {
url: input.slice(url.start, url.end),
}
}
case 'proxy':
{
const [ name ] = node.arguments;
return { name };
};
default:
return false;
};
};
function wrapIdentifier(ctx) {
const { js } = ctx;
js.on(Syntax.Identifier, (node, data, type) => {
js.on('Identifier', (node, data, type) => {
if (type !== 'rewrite') return false;
const { parent } = node;
if (!shouldWrapIdentifier(node.name)) return false;
if (!['location', 'eval', 'parent', 'top'].includes(node.name)) return false;
if (parent.type === Syntax.VariableDeclarator && parent.id === node) return false;
if ((parent.type === Syntax.AssignmentExpression || parent.type === Syntax.AssignmentPattern) && parent.left === node) return false;
if ((parent.type === Syntax.FunctionExpression || parent.type === Syntax.FunctionDeclaration) && parent.id === node) return false;
@ -393,14 +101,40 @@ function wrapIdentifier(ctx) {
if (parent.type === Syntax.RestElement) return false;
if (parent.type === Syntax.ExportSpecifier) return false;
if (parent.type === Syntax.ImportSpecifier) return false;
data.changes.push({
start: node.start,
end: node.end,
node: `${uvMethods.proxy}(${node.name}, __uv)`
node: '__uv.$get(' + node.name + ')'
});
});
};
function wrapEval(ctx) {
const { js } = ctx;
js.on('CallExpression', (node, data, type) => {
if (type !== 'rewrite') return false;
if (!node.arguments.length) return false;
if (node.callee.type !== 'Identifier') return false;
if (node.callee.name !== 'eval') return false;
const [ script ] = node.arguments;
data.changes.push({
node: '__uv.js.rewrite(',
start: script.start,
end: script.start,
})
node.iterateEnd = function() {
data.changes.push({
node: ')',
start: script.end,
end: script.end,
});
};
});
};
function importDeclaration(ctx) {
const { js } = ctx;
js.on(Syntax.Literal, (node, data, type) => {
@ -420,7 +154,7 @@ function dynamicImport(ctx) {
js.on(Syntax.ImportExpression, (node, data, type) => {
if (type !== 'rewrite') return false;
data.changes.push({
node: uvMethods.url + '(',
node: '__uv.rewriteUrl(',
start: node.source.start,
end: node.source.start,
})
@ -434,41 +168,76 @@ function dynamicImport(ctx) {
});
};
function destructureDeclaration(ctx) {
function unwrap(ctx) {
const { js } = ctx;
js.on(Syntax.VariableDeclarator, (node, data, type) => {
if (type !== 'rewrite') return false;
if (node.id.type !== Syntax.ObjectPattern) return false;
const names = [];
js.on('CallExpression', (node, data, type) => {
if (type !== 'source') return false;
if (!isWrapped(node.callee)) return false;
for (const { key } of node.id.properties) {
names.push(key.name);
};
console.log(names);
switch(node.callee.property.name) {
case '$wrap':
if (!node.arguments || node.parent.type !== Syntax.MemberExpression || node.parent.property !== node) return false;
const [ property ] = node.arguments;
data.changes.push({
node: uvMethods.object + '(',
start: node.init.start,
end: node.init.start,
})
start: node.callee.start,
end: property.start,
});
node.iterateEnd = function() {
data.changes.push({
node: ')',
start: node.init.end,
end: node.init.end,
start: node.end - 2,
end: node.end,
});
};
break;
case '$get':
case 'rewriteUrl':
const [ arg ] = node.arguments;
data.changes.push({
start: node.callee.start,
end: arg.start,
});
node.iterateEnd = function() {
data.changes.push({
start: node.end - 1,
end: node.end,
});
};
break;
case 'rewrite':
const [ script ] = node.arguments;
data.changes.push({
start: node.callee.start,
end: script.start,
});
node.iterateEnd = function() {
data.changes.push({
start: node.end - 1,
end: node.end,
});
};
};
});
};
function shouldWrapProperty(name) {
return name === 'eval' || name === 'postMessage' || name === 'location' || name === 'parent' || name === 'top';
function isWrapped(node) {
if (node.type !== Syntax.MemberExpression) return false;
if (node.property.name === 'rewrite' && isWrapped(node.object)) return true;
if (node.object.type !== Syntax.Identifier || node.object.name !== '__uv') return false;
if (!['js', '$get', '$wrap', 'rewriteUrl'].includes(node.property.name)) return false;
return true;
};
function shouldWrapIdentifier(name) {
return name === 'postMessage' || name === 'location' || name === 'parent' || name === 'top';
function computedProperty(parent) {
if (!parent.computed) return false;
const { property: node } = parent;
if (node.type === 'Literal' && !['location', 'top', 'parent']) return false;
return true;
};
export { getProperty, destructureDeclaration, setProperty, call, sourceMethods, importDeclaration, dynamicImport, wrapIdentifier, wrapEval };
export { property, wrapEval, dynamicImport, importDeclaration, identifier, unwrap };

View file

@ -11,12 +11,12 @@ function request(request, response) {
remoteRequest.on('response', remoteResponse => {
const send = prepareResponse(remoteResponse);
response.writeHead(...send);
remoteResponse.pipe(response);
});
remoteRequest.on('error', e => {
console.log(e);
json(response, 500, {
error: e.toString()
});
@ -24,7 +24,6 @@ function request(request, response) {
request.pipe(remoteRequest);
} catch(e) {
console.log(e);
json(response, 500, {
error: e.toString()
});

View file

@ -13,8 +13,6 @@ addEventListener('fetch', async event => {
sendHeaders.Referer = 'https://www.google.com' + request.referrer.slice(location.origin.length);
};
console.log(Object.fromEntries([...request.headers.entries()]), sendHeaders);
event.respondWith(
fetch('/bare/v1/', {
headers: {

View file

@ -1,7 +1,7 @@
export function prepareResponse({ headers, statusCode, statusMessage }) {
const sendHeaders = {
'x-bare-headers': JSON.stringify(headers),
'x-bare-status': statusCode,
'x-bare-status': statusCode.toString(),
'x-bare-status-text': statusMessage,
};

14
worker/context.js Normal file
View file

@ -0,0 +1,14 @@
class RequestContext {
constructor(ctx = {}) {
this.url = ctx.url || '';
this.method = ctx.method || 'GET';
this.body = ctx.body || null;
this.headers = ctx.headers || {};
this.mode = ctx.mode || 'cors';
this.redirect = ctx.redirect || 'manual';
this.referrer = ctx.referrer || '';
this.destination = ctx.destination || '';
};
};
export { RequestContext };

10
worker/index.js Normal file
View file

@ -0,0 +1,10 @@
import { RequestContext } from "./context";
class ServiceWorkerProxy extends EventTarget {
constructor() {
};
static createRequest(options = {}) {
return new RequestContext(options);
};
};