mirror of
https://github.com/MercuryWorkshop/scramjet.git
synced 2025-05-13 22:40:01 -04:00
worker rewriting
This commit is contained in:
parent
2598bee87b
commit
f6c3c13d1e
22 changed files with 543 additions and 392 deletions
|
@ -1,7 +1,7 @@
|
|||
import { client } from ".";
|
||||
|
||||
// goodybye spyware~
|
||||
client.Proxy(navigator, "sendBeacon", {
|
||||
client.Proxy("navigator.sendBeacon", {
|
||||
apply(ctx) {
|
||||
ctx.return(null);
|
||||
},
|
||||
|
|
|
@ -1,10 +1,47 @@
|
|||
Object.defineProperty(document, "cookie", {
|
||||
get() {
|
||||
return "";
|
||||
import { parse } from "set-cookie-parser";
|
||||
import { client } from ".";
|
||||
|
||||
client.Trap("Document.prototype.cookie", {
|
||||
get(ctx) {
|
||||
const cookiestring = ctx.get();
|
||||
dbg.log("original cookiestring", cookiestring);
|
||||
//
|
||||
// if (!cookiestring) return "";
|
||||
//
|
||||
//
|
||||
// let string = "";
|
||||
//
|
||||
// for (const cookiestr of cookiestring.split(";")) {
|
||||
// const cookie = parse(cookiestr.trim())[0];
|
||||
// if (cookie.name.startsWith(client.url.hostname + "@")) {
|
||||
// let name = cookie.name.substring(client.url.hostname.length + 1);
|
||||
// string += `${name}=${cookie.value}; `;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return string.trimEnd();
|
||||
|
||||
return "sp_t=00246e00653d39d1341bbe9d10f138c4; OptanonConsent=isGpcEnabled=0&datestamp=Sat+Jul+20+2024+16%3A11%3A26+GMT-0400+(Eastern+Daylight+Time)&version=202405.2.0&browserGpcFlag=0&isIABGlobal=false&hosts=&landingPath=https%3A%2F%2Fopen.spotify.com%2F&groups=BG169%3A1%2Ct00%3A1%2Ci00%3A1%2CBG170%3A1%2Cs00%3A1%2Cf00%3A1%2Cm00%3A1%2Cf11%3A1";
|
||||
},
|
||||
set(value) {
|
||||
console.log("COOKIE SET", value);
|
||||
set(ctx, value: string) {
|
||||
dbg.debug("setting cookie", value);
|
||||
const cookie = parse(value)[0];
|
||||
|
||||
let date = new Date();
|
||||
let expires = cookie.expires;
|
||||
|
||||
dbg.error("expires", expires);
|
||||
// if (expires instanceof Date) {
|
||||
// if (isNaN(expires.getTime())) return;
|
||||
// if (expires.getTime() < date.getTime()) return;
|
||||
// }
|
||||
|
||||
// set.call(document, `${cookie.name}=${cookie.value}`);
|
||||
},
|
||||
});
|
||||
|
||||
delete window.cookieStore;
|
||||
// @ts-ignore
|
||||
delete self.cookieStore;
|
||||
|
||||
// sp_t=00e49dc8-59d0-4b5f-9beb-ec7b67368498; path=/; expires=Invalid Date
|
||||
// OTZ=7653361_72_76_104100_72_446760;path=/;expires=Mon, 19 Aug 2024 20:01:06 GMT;secure
|
||||
|
|
|
@ -14,7 +14,7 @@ const cssProperties = [
|
|||
];
|
||||
// const jsProperties = ["background", "backgroundImage", "mask", "maskImage", "listStyle", "listStyleImage", "borderImage", "borderImageSource", "cursor"];
|
||||
|
||||
client.Proxy(CSSStyleDeclaration.prototype, "setProperty", {
|
||||
client.Proxy("CSSStyleDeclaration.prototype.setProperty", {
|
||||
apply(ctx) {
|
||||
if (cssProperties.includes(ctx.args[0]))
|
||||
ctx.args[1] = rewriteCss(ctx.args[1]);
|
||||
|
|
|
@ -9,7 +9,8 @@ import {
|
|||
} from "./shared";
|
||||
import { documentProxy } from "./window";
|
||||
|
||||
const attrObject = {
|
||||
if ("window" in self) {
|
||||
const attrObject = {
|
||||
nonce: [HTMLElement],
|
||||
integrity: [HTMLScriptElement, HTMLLinkElement],
|
||||
csp: [HTMLIFrameElement],
|
||||
|
@ -27,13 +28,16 @@ const attrObject = {
|
|||
srcdoc: [HTMLIFrameElement],
|
||||
srcset: [HTMLImageElement, HTMLSourceElement],
|
||||
imagesrcset: [HTMLLinkElement],
|
||||
};
|
||||
};
|
||||
|
||||
const attrs = Object.keys(attrObject);
|
||||
const attrs = Object.keys(attrObject);
|
||||
|
||||
for (const attr of attrs) {
|
||||
for (const attr of attrs) {
|
||||
for (const element of attrObject[attr]) {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(element.prototype, attr);
|
||||
const descriptor = Object.getOwnPropertyDescriptor(
|
||||
element.prototype,
|
||||
attr
|
||||
);
|
||||
Object.defineProperty(element.prototype, attr, {
|
||||
get() {
|
||||
if (["src", "data", "href", "action", "formaction"].includes(attr)) {
|
||||
|
@ -66,17 +70,17 @@ for (const attr of attrs) {
|
|||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
declare global {
|
||||
interface Element {
|
||||
$origattrs: Record<string, string>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Element.prototype.$origattrs = {};
|
||||
Element.prototype.$origattrs = {};
|
||||
|
||||
Element.prototype.getAttribute = new Proxy(Element.prototype.getAttribute, {
|
||||
Element.prototype.getAttribute = new Proxy(Element.prototype.getAttribute, {
|
||||
apply(target, thisArg, argArray) {
|
||||
if (attrs.includes(argArray[0]) && thisArg.$origattrs[argArray[0]]) {
|
||||
return thisArg.$origattrs[argArray[0]];
|
||||
|
@ -84,9 +88,9 @@ Element.prototype.getAttribute = new Proxy(Element.prototype.getAttribute, {
|
|||
|
||||
return Reflect.apply(target, thisArg, argArray);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
Element.prototype.setAttribute = new Proxy(Element.prototype.setAttribute, {
|
||||
Element.prototype.setAttribute = new Proxy(Element.prototype.setAttribute, {
|
||||
apply(target, thisArg, argArray) {
|
||||
if (attrs.includes(argArray[0])) {
|
||||
thisArg.$origattrs[argArray[0]] = argArray[1];
|
||||
|
@ -107,14 +111,14 @@ Element.prototype.setAttribute = new Proxy(Element.prototype.setAttribute, {
|
|||
|
||||
return Reflect.apply(target, thisArg, argArray);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
const innerHTML = Object.getOwnPropertyDescriptor(
|
||||
const innerHTML = Object.getOwnPropertyDescriptor(
|
||||
Element.prototype,
|
||||
"innerHTML"
|
||||
);
|
||||
);
|
||||
|
||||
Object.defineProperty(Element.prototype, "innerHTML", {
|
||||
Object.defineProperty(Element.prototype, "innerHTML", {
|
||||
set(value) {
|
||||
if (this instanceof HTMLScriptElement) {
|
||||
value = rewriteJs(value);
|
||||
|
@ -126,13 +130,13 @@ Object.defineProperty(Element.prototype, "innerHTML", {
|
|||
|
||||
return innerHTML.set.call(this, value);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
for (const target of [Node.prototype, MutationObserver.prototype, document]) {
|
||||
for (const target of [Node.prototype, MutationObserver.prototype, document]) {
|
||||
for (const prop in target) {
|
||||
try {
|
||||
if (typeof target[prop] === "function") {
|
||||
client.Proxy(target, prop, {
|
||||
client.RawProxy(target, prop, {
|
||||
apply(ctx) {
|
||||
for (const i in ctx.args) {
|
||||
if (ctx.args[i] === documentProxy) ctx.args[i] = document;
|
||||
|
@ -142,4 +146,5 @@ for (const target of [Node.prototype, MutationObserver.prototype, document]) {
|
|||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { client } from ".";
|
||||
import { encodeUrl } from "./shared";
|
||||
|
||||
client.Proxy(window.history, "pushState", {
|
||||
client.Proxy("history.pushState", {
|
||||
apply(ctx) {
|
||||
ctx.args[2] = encodeUrl(ctx.args[2]);
|
||||
},
|
||||
});
|
||||
|
||||
client.Proxy(window.history, "replaceState", {
|
||||
client.Proxy("history.replaceState", {
|
||||
apply(ctx) {
|
||||
ctx.args[2] = encodeUrl(ctx.args[2]);
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { encodeUrl } from "../shared/rewriters/url";
|
||||
|
||||
window.$sImport = function (base) {
|
||||
self.$sImport = function (base) {
|
||||
return function (url) {
|
||||
const resolved = new URL(url, base).href;
|
||||
|
||||
|
|
|
@ -7,7 +7,9 @@ declare global {
|
|||
$sImport: any;
|
||||
}
|
||||
}
|
||||
type AnyFunction = (...args: any[]) => any;
|
||||
|
||||
//eslint-disable-next-line
|
||||
type AnyFunction = Function;
|
||||
|
||||
type ProxyCtx = {
|
||||
fn: AnyFunction;
|
||||
|
@ -16,17 +18,43 @@ type ProxyCtx = {
|
|||
newTarget: AnyFunction;
|
||||
return: (r: any) => void;
|
||||
};
|
||||
|
||||
class ScramjetClient {
|
||||
Proxy(
|
||||
target: any,
|
||||
prop: string,
|
||||
handler: {
|
||||
type Proxy = {
|
||||
construct?(ctx: ProxyCtx): any;
|
||||
apply?(ctx: ProxyCtx): any;
|
||||
};
|
||||
|
||||
type TrapCtx<T> = {
|
||||
this: any;
|
||||
get: () => T;
|
||||
set: (v: T) => void;
|
||||
};
|
||||
type Trap<T> = {
|
||||
writable?: boolean;
|
||||
value?: any;
|
||||
enumerable?: boolean;
|
||||
configurable?: boolean;
|
||||
get?: (ctx: TrapCtx<T>) => T;
|
||||
set?: (ctx: TrapCtx<T>, v: T) => void;
|
||||
};
|
||||
|
||||
class ScramjetClient {
|
||||
Proxy(name: string | string[], handler: Proxy) {
|
||||
if (Array.isArray(name)) {
|
||||
for (const n of name) {
|
||||
this.Proxy(n, handler);
|
||||
}
|
||||
) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const split = name.split(".");
|
||||
const prop = split.pop();
|
||||
const target = split.reduce((a, b) => a?.[b], self);
|
||||
this.RawProxy(target, prop, handler);
|
||||
}
|
||||
RawProxy(target: any, prop: string, handler: Proxy) {
|
||||
if (!target) return;
|
||||
if (!prop) return;
|
||||
if (!Reflect.has(target, prop)) return;
|
||||
|
||||
const value = Reflect.get(target, prop);
|
||||
|
@ -36,14 +64,14 @@ class ScramjetClient {
|
|||
|
||||
if (handler.construct) {
|
||||
h.construct = function (
|
||||
target: any,
|
||||
constructor: any,
|
||||
argArray: any[],
|
||||
newTarget: AnyFunction
|
||||
) {
|
||||
let returnValue: any = null;
|
||||
|
||||
const ctx: ProxyCtx = {
|
||||
fn: target,
|
||||
fn: constructor,
|
||||
this: null,
|
||||
args: argArray,
|
||||
newTarget: newTarget,
|
||||
|
@ -63,11 +91,11 @@ class ScramjetClient {
|
|||
}
|
||||
|
||||
if (handler.apply) {
|
||||
h.apply = function (target: any, thisArg: any, argArray: any[]) {
|
||||
h.apply = function (fn: any, thisArg: any, argArray: any[]) {
|
||||
let returnValue: any = null;
|
||||
|
||||
const ctx: ProxyCtx = {
|
||||
fn: target,
|
||||
fn,
|
||||
this: thisArg,
|
||||
args: argArray,
|
||||
newTarget: null,
|
||||
|
@ -88,36 +116,77 @@ class ScramjetClient {
|
|||
|
||||
target[prop] = new Proxy(value, h);
|
||||
}
|
||||
Trap<T>(name: string | string[], descriptor: Trap<T>) {
|
||||
if (Array.isArray(name)) {
|
||||
for (const n of name) {
|
||||
this.Trap(n, descriptor);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const split = name.split(".");
|
||||
const prop = split.pop();
|
||||
const target = split.reduce((a, b) => a?.[b], self);
|
||||
|
||||
this.RawTrap(target, prop, descriptor);
|
||||
}
|
||||
RawTrap<T>(target: any, prop: string, descriptor: Trap<T>) {
|
||||
if (!target) return;
|
||||
if (!prop) return;
|
||||
if (!Reflect.has(target, prop)) return;
|
||||
|
||||
const oldDescriptor = Object.getOwnPropertyDescriptor(target, prop);
|
||||
|
||||
const ctx: TrapCtx<T> = {
|
||||
this: null,
|
||||
get: function () {
|
||||
return oldDescriptor && oldDescriptor.get.call(this.this);
|
||||
},
|
||||
set: function (v: T) {
|
||||
oldDescriptor && oldDescriptor.set.call(this.this, v);
|
||||
},
|
||||
};
|
||||
|
||||
delete target[prop];
|
||||
|
||||
const desc: PropertyDescriptor = {};
|
||||
|
||||
if (descriptor.get) {
|
||||
desc.get = function () {
|
||||
ctx.this = this;
|
||||
|
||||
return descriptor.get(ctx);
|
||||
};
|
||||
} else if (oldDescriptor?.get) {
|
||||
desc.get = oldDescriptor.get;
|
||||
}
|
||||
|
||||
if (descriptor.set) {
|
||||
desc.set = function (v: T) {
|
||||
ctx.this = this;
|
||||
|
||||
descriptor.set(ctx, v);
|
||||
};
|
||||
} else if (oldDescriptor?.set) {
|
||||
desc.set = oldDescriptor.set;
|
||||
}
|
||||
|
||||
if (descriptor.enumerable) desc.enumerable = descriptor.enumerable;
|
||||
else if (oldDescriptor?.enumerable)
|
||||
desc.enumerable = oldDescriptor.enumerable;
|
||||
if (descriptor.configurable) desc.configurable = descriptor.configurable;
|
||||
else if (oldDescriptor?.configurable)
|
||||
desc.configurable = oldDescriptor.configurable;
|
||||
|
||||
Object.defineProperty(target, prop, desc);
|
||||
}
|
||||
|
||||
get url(): URL {
|
||||
return new URL(decodeUrl(location.href));
|
||||
}
|
||||
|
||||
async init() {
|
||||
function b64(buffer) {
|
||||
let binary = "";
|
||||
let bytes = new Uint8Array(buffer);
|
||||
let len = bytes.byteLength;
|
||||
for (let i = 0; i < len; i++) {
|
||||
binary += String.fromCharCode(bytes[i]);
|
||||
}
|
||||
|
||||
return window.btoa(binary);
|
||||
}
|
||||
const arraybuffer = await (await fetch("/scramjet.png")).arrayBuffer();
|
||||
console.log(
|
||||
"%cb",
|
||||
`
|
||||
background-image: url(data:image/png;base64,${b64(arraybuffer)});
|
||||
color: transparent;
|
||||
padding-left: 200px;
|
||||
padding-bottom: 100px;
|
||||
background-size: contain;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
`
|
||||
);
|
||||
}
|
||||
async init() {}
|
||||
}
|
||||
|
||||
export const client = new ScramjetClient();
|
||||
|
|
|
@ -1,18 +1,25 @@
|
|||
import { client } from ".";
|
||||
import { decodeUrl } from "../shared/rewriters/url";
|
||||
|
||||
// const descriptor = Object.getOwnPropertyDescriptor(window, "origin");
|
||||
delete window.origin;
|
||||
|
||||
Object.defineProperty(window, "origin", {
|
||||
client.Trap("origin", {
|
||||
get() {
|
||||
return new URL(decodeUrl(location.href)).origin;
|
||||
return client.url.origin;
|
||||
},
|
||||
set() {
|
||||
return false;
|
||||
},
|
||||
});
|
||||
|
||||
Object.defineProperty(document, "URL", {
|
||||
client.Trap("document.URL", {
|
||||
get() {
|
||||
return client.url;
|
||||
},
|
||||
set() {
|
||||
return false;
|
||||
},
|
||||
});
|
||||
|
||||
client.Trap("document.baseURI", {
|
||||
get() {
|
||||
return decodeUrl(location.href);
|
||||
},
|
||||
|
@ -21,18 +28,9 @@ Object.defineProperty(document, "URL", {
|
|||
},
|
||||
});
|
||||
|
||||
Object.defineProperty(document, "baseURI", {
|
||||
client.Trap("document.domain", {
|
||||
get() {
|
||||
return decodeUrl(location.href);
|
||||
},
|
||||
set() {
|
||||
return false;
|
||||
},
|
||||
});
|
||||
|
||||
Object.defineProperty(document, "domain", {
|
||||
get() {
|
||||
return new URL(decodeUrl(location.href)).hostname;
|
||||
return client.url.hostname;
|
||||
},
|
||||
set() {
|
||||
return false;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { client } from ".";
|
||||
|
||||
client.Proxy(window, "postMessage", {
|
||||
client.Proxy("window.postMessage", {
|
||||
apply(ctx) {
|
||||
if (typeof ctx.args[1] === "string") ctx.args[1] = "*";
|
||||
},
|
||||
|
|
|
@ -3,25 +3,25 @@
|
|||
import { client } from "..";
|
||||
import { encodeUrl, rewriteHeaders } from "../shared";
|
||||
|
||||
client.Proxy(window, "fetch", {
|
||||
client.Proxy("fetch", {
|
||||
apply(ctx) {
|
||||
ctx.args[0] = encodeUrl(ctx.args[0]);
|
||||
},
|
||||
});
|
||||
|
||||
client.Proxy(window, "Headers", {
|
||||
client.Proxy("Headers", {
|
||||
construct(ctx) {
|
||||
ctx.args[0] = rewriteHeaders(ctx.args[0]);
|
||||
},
|
||||
});
|
||||
|
||||
client.Proxy(window, "Request", {
|
||||
client.Proxy("Request", {
|
||||
construct(ctx) {
|
||||
if (typeof ctx.args[0] === "string") ctx.args[0] = encodeUrl(ctx.args[0]);
|
||||
},
|
||||
});
|
||||
|
||||
client.Proxy(Response, "redirect", {
|
||||
client.Proxy("Response.redirect", {
|
||||
apply(ctx) {
|
||||
ctx.args[0] = encodeUrl(ctx.args[0]);
|
||||
},
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import { client } from "..";
|
||||
import { BareClient } from "../shared";
|
||||
const bare = new BareClient();
|
||||
|
||||
client.Proxy(window, "WebSocket", {
|
||||
if ("window" in self) {
|
||||
const bare = new BareClient();
|
||||
|
||||
client.Proxy("WebSocket", {
|
||||
construct(ctx) {
|
||||
ctx.return(
|
||||
bare.createWebSocket(
|
||||
|
@ -17,4 +19,5 @@ client.Proxy(window, "WebSocket", {
|
|||
)
|
||||
);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { client } from "..";
|
||||
import { encodeUrl, rewriteHeaders } from "../shared";
|
||||
|
||||
client.Proxy(XMLHttpRequest.prototype, "open", {
|
||||
client.Proxy("XMLHttpRequest.prototype.open", {
|
||||
apply(ctx) {
|
||||
if (ctx.args[1]) ctx.args[1] = encodeUrl(ctx.args[1]);
|
||||
},
|
||||
});
|
||||
|
||||
client.Proxy(XMLHttpRequest.prototype, "setRequestHeader", {
|
||||
client.Proxy("XMLHttpRequest.prototype.setRequestHeader", {
|
||||
apply(ctx) {
|
||||
let headerObject = Object.fromEntries([ctx.args]);
|
||||
headerObject = rewriteHeaders(headerObject);
|
||||
|
|
|
@ -1,27 +1,39 @@
|
|||
import { locationProxy } from "./location";
|
||||
import { documentProxy, windowProxy } from "./window";
|
||||
|
||||
export const iswindow = "window" in self;
|
||||
export const isworker = "WorkerGlobalScope" in self;
|
||||
export const issw = "ServiceWorkerGlobalScope" in self;
|
||||
export const isdedicated = "DedicatedWorkerGlobalScope" in self;
|
||||
export const isshared = "SharedWorkerGlobalScope" in self;
|
||||
|
||||
function scope(identifier: any) {
|
||||
// this will break iframe postmessage!
|
||||
if (
|
||||
identifier instanceof Window ||
|
||||
iswindow &&
|
||||
(identifier instanceof Window ||
|
||||
identifier instanceof top.window.Window ||
|
||||
identifier instanceof parent.window.Window
|
||||
identifier instanceof parent.window.Window)
|
||||
) {
|
||||
return windowProxy;
|
||||
} else if (identifier instanceof Location) {
|
||||
} else if (
|
||||
(iswindow && identifier instanceof Location) ||
|
||||
(isworker && identifier instanceof WorkerLocation)
|
||||
) {
|
||||
return locationProxy;
|
||||
} else if (identifier instanceof Document) {
|
||||
} else if (iswindow && identifier instanceof Document) {
|
||||
return documentProxy;
|
||||
} else if (isworker && identifier instanceof WorkerGlobalScope) {
|
||||
return windowProxy;
|
||||
}
|
||||
|
||||
return identifier;
|
||||
}
|
||||
|
||||
// shorthand because this can get out of hand reall quickly
|
||||
window.$s = scope;
|
||||
self.$s = scope;
|
||||
|
||||
window.$tryset = function (lhs: any, op: string, rhs: any) {
|
||||
self.$tryset = function (lhs: any, op: string, rhs: any) {
|
||||
if (lhs instanceof Location) {
|
||||
// @ts-ignore
|
||||
locationProxy.href = rhs;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { client } from ".";
|
||||
|
||||
const handler: ProxyHandler<Storage> = {
|
||||
if ("window" in self) {
|
||||
const handler: ProxyHandler<Storage> = {
|
||||
get(target, prop) {
|
||||
switch (prop) {
|
||||
case "getItem":
|
||||
|
@ -82,16 +83,17 @@ const handler: ProxyHandler<Storage> = {
|
|||
|
||||
return true;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const realLocalStorage = window.localStorage;
|
||||
const realSessionStorage = window.sessionStorage;
|
||||
const realLocalStorage = window.localStorage;
|
||||
const realSessionStorage = window.sessionStorage;
|
||||
|
||||
const localStorageProxy = new Proxy(window.localStorage, handler);
|
||||
const sessionStorageProxy = new Proxy(window.sessionStorage, handler);
|
||||
const localStorageProxy = new Proxy(window.localStorage, handler);
|
||||
const sessionStorageProxy = new Proxy(window.sessionStorage, handler);
|
||||
|
||||
delete window.localStorage;
|
||||
delete window.sessionStorage;
|
||||
delete window.localStorage;
|
||||
delete window.sessionStorage;
|
||||
|
||||
window.localStorage = localStorageProxy;
|
||||
window.sessionStorage = sessionStorageProxy;
|
||||
window.localStorage = localStorageProxy;
|
||||
window.sessionStorage = sessionStorageProxy;
|
||||
}
|
||||
|
|
|
@ -30,10 +30,12 @@
|
|||
// },
|
||||
// });
|
||||
|
||||
//@ts-nocheck
|
||||
delete window.TrustedHTML;
|
||||
delete window.TrustedScript;
|
||||
delete window.TrustedScriptURL;
|
||||
delete window.TrustedTypePolicy;
|
||||
delete window.TrustedTypePolicyFactory;
|
||||
delete window.trustedTypes;
|
||||
if ("window" in self) {
|
||||
//@ts-nocheck
|
||||
delete window.TrustedHTML;
|
||||
delete window.TrustedScript;
|
||||
delete window.TrustedScriptURL;
|
||||
delete window.TrustedTypePolicy;
|
||||
delete window.TrustedTypePolicyFactory;
|
||||
delete window.trustedTypes;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { client } from ".";
|
|||
import { encodeUrl } from "../shared/rewriters/url";
|
||||
import { locationProxy } from "./location";
|
||||
|
||||
export const windowProxy = new Proxy(window, {
|
||||
export const windowProxy = new Proxy(self, {
|
||||
get(target, prop) {
|
||||
const propIsString = typeof prop === "string";
|
||||
if (propIsString && prop === "location") {
|
||||
|
@ -13,7 +13,7 @@ export const windowProxy = new Proxy(window, {
|
|||
) {
|
||||
return windowProxy;
|
||||
} else if (propIsString && prop == "parent") {
|
||||
return window.parent;
|
||||
return self.parent;
|
||||
} else if (propIsString && prop === "$scramjet") {
|
||||
return;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ export const windowProxy = new Proxy(window, {
|
|||
if (typeof value === "function") {
|
||||
return new Proxy(value, {
|
||||
apply(_target, thisArg, argArray) {
|
||||
return value.apply(window, argArray);
|
||||
return value.apply(self, argArray);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ export const windowProxy = new Proxy(window, {
|
|||
},
|
||||
});
|
||||
|
||||
export const documentProxy = new Proxy(document, {
|
||||
export const documentProxy = new Proxy(self.document || {}, {
|
||||
get(target, prop) {
|
||||
const propIsString = typeof prop === "string";
|
||||
|
||||
|
@ -60,7 +60,7 @@ export const documentProxy = new Proxy(document, {
|
|||
if (typeof value === "function") {
|
||||
return new Proxy(value, {
|
||||
apply(_target, thisArg, argArray) {
|
||||
return value.apply(document, argArray);
|
||||
return value.apply(self.document, argArray);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -79,32 +79,16 @@ export const documentProxy = new Proxy(document, {
|
|||
},
|
||||
});
|
||||
|
||||
client.Proxy(Function.prototype, "apply", {
|
||||
client.Proxy(
|
||||
[
|
||||
"Function.prototype.call",
|
||||
"Function.prototype.bind",
|
||||
"Function.prototype.apply",
|
||||
],
|
||||
{
|
||||
apply(ctx) {
|
||||
if (ctx.args[0] === windowProxy) {
|
||||
ctx.args[0] = window;
|
||||
} else if (ctx.args[0] === documentProxy) {
|
||||
ctx.args[0] = document;
|
||||
}
|
||||
if (ctx.args[0] === windowProxy) ctx.args[0] = window;
|
||||
if (ctx.args[0] === documentProxy) ctx.args[0] = document;
|
||||
},
|
||||
});
|
||||
|
||||
client.Proxy(Function.prototype, "call", {
|
||||
apply(ctx) {
|
||||
if (ctx.args[0] === windowProxy) {
|
||||
ctx.args[0] = window;
|
||||
} else if (ctx.args[0] === documentProxy) {
|
||||
ctx.args[0] = document;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
client.Proxy(Function.prototype, "bind", {
|
||||
apply(ctx) {
|
||||
if (ctx.args[0] === windowProxy) {
|
||||
ctx.args[0] = window;
|
||||
} else if (ctx.args[0] === documentProxy) {
|
||||
ctx.args[0] = document;
|
||||
}
|
||||
},
|
||||
});
|
||||
);
|
||||
|
|
|
@ -1,37 +1,38 @@
|
|||
import { client } from ".";
|
||||
import { encodeUrl } from "./shared";
|
||||
|
||||
Worker = new Proxy(Worker, {
|
||||
construct(target, argArray) {
|
||||
argArray[0] = encodeUrl(argArray[0]);
|
||||
client.Proxy("Worker", {
|
||||
construct({ args }) {
|
||||
if (args[0] instanceof URL) args[0] = args[0].href;
|
||||
if (args[0].startsWith("blob:") || args[0].startsWith("data:")) {
|
||||
// TODO
|
||||
return;
|
||||
}
|
||||
|
||||
// target is a reference to the object that you are proxying
|
||||
// Reflect.construct is just a wrapper for calling target
|
||||
// you could do new target(...argArray) and it would work the same effectively
|
||||
args[0] = encodeUrl(args[0]) + "?dest=worker";
|
||||
|
||||
return Reflect.construct(target, argArray);
|
||||
if (args[1] && args[1].type === "module") {
|
||||
args[0] += "&type=module";
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Worklet.prototype.addModule = new Proxy(Worklet.prototype.addModule, {
|
||||
if ("window" in self) {
|
||||
Worklet.prototype.addModule = new Proxy(Worklet.prototype.addModule, {
|
||||
apply(target, thisArg, argArray) {
|
||||
argArray[0] = encodeUrl(argArray[0]);
|
||||
|
||||
return Reflect.apply(target, thisArg, argArray);
|
||||
},
|
||||
});
|
||||
|
||||
if ("serviceWorker" in window.navigator) {
|
||||
});
|
||||
//@ts-expect-error temporary until nested sw support
|
||||
delete window.Navigator.prototype.serviceWorker;
|
||||
}
|
||||
// broken
|
||||
|
||||
// window.importScripts = new Proxy(window.importScripts, {
|
||||
// apply(target, thisArg, argArray) {
|
||||
// for (const i in argArray) {
|
||||
// argArray[i] = encodeUrl(argArray[i]);
|
||||
// }
|
||||
|
||||
// return Reflect.apply(target, thisArg, argArray);
|
||||
// },
|
||||
// });
|
||||
client.Proxy("importScripts", {
|
||||
apply(ctx) {
|
||||
for (const i in ctx.args) {
|
||||
ctx.args[i] = encodeUrl(ctx.args[i]);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
30
src/log.ts
30
src/log.ts
|
@ -1,25 +1,24 @@
|
|||
const _dbg = {
|
||||
export default {
|
||||
fmt: function (severity: string, message: string, ...args: any[]) {
|
||||
const old = Error.prepareStackTrace;
|
||||
|
||||
Error.prepareStackTrace = (_, stack) => {
|
||||
stack.shift(); // stack();
|
||||
stack.shift(); // fmt();
|
||||
stack.shift();
|
||||
|
||||
for (let i = 0; i < stack.length; i++) {
|
||||
if (Object.values(this).includes(stack[i].getFunction())) {
|
||||
stack.splice(i, 1);
|
||||
let fmt = "";
|
||||
for (let i = 1; i < Math.min(2, stack.length); i++) {
|
||||
if (stack[i].getFunctionName()) {
|
||||
// const f = stack[i].getThis()?.constructor?.name;
|
||||
// if (f) fmt += `${f}.`
|
||||
fmt += `${stack[i].getFunctionName()} -> ` + fmt;
|
||||
}
|
||||
}
|
||||
|
||||
let frame = stack[0];
|
||||
while (!frame?.getFunctionName() || !frame) {
|
||||
frame = stack.shift();
|
||||
}
|
||||
fmt += stack[0].getFunctionName();
|
||||
|
||||
const fn = stack[0].getFunctionName();
|
||||
|
||||
return `${fn}()`;
|
||||
return fmt;
|
||||
};
|
||||
|
||||
const fmt = (function stack() {
|
||||
|
@ -59,6 +58,8 @@ background-color: ${bg};
|
|||
color: ${fg};
|
||||
padding: ${padding}px;
|
||||
font-weight: bold;
|
||||
font-family: monospace;
|
||||
font-size: 0.9em;
|
||||
`,
|
||||
`
|
||||
${severity === "debug" ? "color: gray" : ""}
|
||||
|
@ -79,10 +80,3 @@ ${severity === "debug" ? "color: gray" : ""}
|
|||
this.fmt("debug", message, ...args);
|
||||
},
|
||||
};
|
||||
|
||||
for (const key in _dbg) {
|
||||
_dbg[key] = (0, eval)("(" + _dbg[key].toString() + ")");
|
||||
}
|
||||
self._dbg = _dbg;
|
||||
|
||||
export default _dbg;
|
||||
|
|
|
@ -1,11 +1,32 @@
|
|||
import { rewriteJs } from "./js";
|
||||
export function rewriteWorkers(js: string, origin?: URL) {
|
||||
let str = new String().toString();
|
||||
//
|
||||
// ["codecs", "config", "shared", "client"].forEach((script) => {
|
||||
// str += `import "${self.$scramjet.config[script]}"\n`;
|
||||
// });
|
||||
// str += rewriteJs(js, origin);
|
||||
|
||||
return js;
|
||||
const clientscripts = ["codecs", "config", "shared", "client"];
|
||||
export function rewriteWorkers(js: string | ArrayBuffer, origin?: URL) {
|
||||
let dest = origin.searchParams.get("dest");
|
||||
let type = origin.searchParams.get("type");
|
||||
|
||||
origin.search = "";
|
||||
|
||||
let str = "";
|
||||
|
||||
if (type === "module") {
|
||||
for (const script of clientscripts) {
|
||||
console.log("Import", script, self.$scramjet);
|
||||
str += `import "${self.$scramjet.config[script]}"\n`;
|
||||
}
|
||||
} else {
|
||||
for (const script of clientscripts) {
|
||||
str += `importScripts("${self.$scramjet.config[script]}");\n`;
|
||||
}
|
||||
}
|
||||
|
||||
let rewritten = rewriteJs(js, origin);
|
||||
if (rewritten instanceof Uint8Array) {
|
||||
rewritten = new TextDecoder().decode(rewritten);
|
||||
}
|
||||
str += "\n" + rewritten;
|
||||
|
||||
dbg.log("Rewrite", type, dest, str);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ async function handleResponse(
|
|||
break;
|
||||
case "sharedworker":
|
||||
case "worker":
|
||||
responseBody = rewriteWorkers(await response.text(), url);
|
||||
responseBody = rewriteWorkers(await response.arrayBuffer(), url);
|
||||
break;
|
||||
default:
|
||||
responseBody = response.body;
|
||||
|
|
25
static/ui.js
25
static/ui.js
|
@ -145,6 +145,29 @@ function App() {
|
|||
`;
|
||||
}
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
window.addEventListener("load", async () => {
|
||||
document.body.appendChild(h(App));
|
||||
function b64(buffer) {
|
||||
let binary = "";
|
||||
let bytes = new Uint8Array(buffer);
|
||||
let len = bytes.byteLength;
|
||||
for (let i = 0; i < len; i++) {
|
||||
binary += String.fromCharCode(bytes[i]);
|
||||
}
|
||||
|
||||
return btoa(binary);
|
||||
}
|
||||
const arraybuffer = await (await fetch("/scramjet.png")).arrayBuffer();
|
||||
console.log(
|
||||
"%cb",
|
||||
`
|
||||
background-image: url(data:image/png;base64,${b64(arraybuffer)});
|
||||
color: transparent;
|
||||
padding-left: 200px;
|
||||
padding-bottom: 100px;
|
||||
background-size: contain;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
`
|
||||
);
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue