ScramjetClient.SCRAMJET -> SCRAMJETCLIENT

This commit is contained in:
velzie 2024-08-30 16:59:52 -04:00
parent 2050fa140c
commit 5f77342d8d
No known key found for this signature in database
GPG key ID: 048413F95F0DDE1F
11 changed files with 82 additions and 50 deletions

View file

@ -1,3 +1,4 @@
import { SCRAMJETCLIENT } from "../symbols";
import { createDocumentProxy } from "./document";
import { createGlobalProxy } from "./global";
import { getOwnPropertyDescriptorHandler } from "./helpers";
@ -43,8 +44,6 @@ export type Trap<T> = {
};
export class ScramjetClient {
static SCRAMJET = Symbol.for("scramjet client global");
documentProxy: any;
globalProxy: any;
locationProxy: any;
@ -76,7 +75,7 @@ export class ScramjetClient {
this.locationProxy = createLocationProxy(this, global);
this.globalProxy = createGlobalProxy(this, global);
global[ScramjetClient.SCRAMJET] = this;
global[SCRAMJETCLIENT] = this;
}
loadcookies(cookiestr: string) {
@ -175,6 +174,7 @@ export class ScramjetClient {
if (handler.apply) {
h.apply = function (fn: any, thisArg: any, argArray: any[]) {
let returnValue: any = null;
let earlyreturn = false;
const ctx: ProxyCtx = {
fn,
@ -182,6 +182,7 @@ export class ScramjetClient {
args: argArray,
newTarget: null,
return: (r: any) => {
earlyreturn = true;
returnValue = r;
},
};
@ -213,7 +214,7 @@ export class ScramjetClient {
delete Error.prepareStackTrace;
if (returnValue) {
if (earlyreturn) {
return returnValue;
}

View file

@ -1,3 +1,4 @@
import { SCRAMJETCLIENT } from "../../symbols";
import { ScramjetClient } from "../client";
import { nativeGetOwnPropertyDescriptor } from "../natives";
import { config, decodeUrl, htmlRules, unrewriteHtml } from "../shared";
@ -127,8 +128,8 @@ export default function (client: ScramjetClient, self: typeof window) {
get(ctx) {
const realwin = ctx.get() as Window;
if (ScramjetClient.SCRAMJET in realwin.self) {
return realwin.self[ScramjetClient.SCRAMJET].globalProxy.window;
if (SCRAMJETCLIENT in realwin.self) {
return realwin.self[SCRAMJETCLIENT].globalProxy.window;
} else {
// hook the iframe
const newclient = new ScramjetClient(realwin.self);
@ -145,8 +146,8 @@ export default function (client: ScramjetClient, self: typeof window) {
client.descriptors["HTMLIFrameElement.prototype.contentWindow"].get;
const realwin = contentwindow.apply(ctx.this);
if (ScramjetClient.SCRAMJET in realwin.self) {
return realwin.self[ScramjetClient.SCRAMJET].documentProxy;
if (SCRAMJETCLIENT in realwin.self) {
return realwin.self[SCRAMJETCLIENT].documentProxy;
} else {
const newclient = new ScramjetClient(realwin.self);
newclient.hook();
@ -175,7 +176,7 @@ export default function (client: ScramjetClient, self: typeof window) {
let doc = ctx.get() as Document | null;
if (!doc) return null;
let scram: ScramjetClient = doc[ScramjetClient.SCRAMJET];
let scram: ScramjetClient = doc[SCRAMJETCLIENT];
if (!scram) return doc; // ??
return scram.documentProxy;

View file

@ -1,5 +1,6 @@
import { encodeUrl } from "../shared";
import { ScramjetClient } from "../client";
import { SCRAMJETCLIENT } from "../../symbols";
export default function (client: ScramjetClient) {
client.Proxy("window.open", {
@ -13,10 +14,8 @@ export default function (client: ScramjetClient) {
if (!realwin) return ctx.return(realwin);
if (ScramjetClient.SCRAMJET in realwin.self) {
return ctx.return(
realwin.self[ScramjetClient.SCRAMJET].globalProxy.window
);
if (SCRAMJETCLIENT in realwin.self) {
return ctx.return(realwin.self[SCRAMJETCLIENT].globalProxy.window);
} else {
const newclient = new ScramjetClient(realwin.self);
// hook the opened window
@ -32,8 +31,8 @@ export default function (client: ScramjetClient) {
get(ctx) {
const realwin = ctx.get() as Window;
if (realwin && ScramjetClient.SCRAMJET in realwin.self) {
return realwin.self[ScramjetClient.SCRAMJET].globalProxy;
if (realwin && SCRAMJETCLIENT in realwin.self) {
return realwin.self[SCRAMJETCLIENT].globalProxy;
} else {
// the opener has to have been already hooked, so if we reach here then it's a real window
return undefined;

View file

@ -1,5 +1,6 @@
// entrypoint for scramjet.client.js
import { SCRAMJETCLIENT } from "../symbols";
import { ScramjetClient } from "./client";
import { ScramjetServiceWorkerRuntime } from "./swruntime";
@ -13,7 +14,7 @@ export const isemulatedsw =
dbg.log("scrammin");
// if it already exists, that means the handlers have probably already been setup by the parent document
if (!(ScramjetClient.SCRAMJET in self)) {
if (!(SCRAMJETCLIENT in <Partial<typeof self>>self)) {
const client = new ScramjetClient(self);
if (self.COOKIE) client.loadcookies(self.COOKIE);

View file

@ -1,4 +1,5 @@
import { iswindow } from "..";
import { SCRAMJETCLIENT } from "../../symbols";
import { ScramjetClient } from "../client";
import { getOwnPropertyDescriptorHandler } from "../helpers";
import { nativeGetOwnPropertyDescriptor } from "../natives";
@ -22,7 +23,7 @@ export default function (client: ScramjetClient, self: Self) {
return this.ports;
},
source() {
let scram: ScramjetClient = this.source[ScramjetClient.SCRAMJET];
let scram: ScramjetClient = this.source[SCRAMJETCLIENT];
if (scram) return scram.globalProxy;

View file

@ -1,4 +1,5 @@
import { iswindow, isworker } from "..";
import { SCRAMJETCLIENT } from "../../symbols";
import { ScramjetClient } from "../client";
import { config } from "../shared";
@ -15,9 +16,9 @@ export default function (client: ScramjetClient, self: typeof globalThis) {
if (iswindow && identifier instanceof self.Window) {
return client.globalProxy;
} else if (iswindow && identifier instanceof self.parent.self.Window) {
if (ScramjetClient.SCRAMJET in self.parent.self) {
if (SCRAMJETCLIENT in self.parent.self) {
// ... then we're in a subframe, and the parent frame is also in a proxy context, so we should return its proxy
return self.parent.self[ScramjetClient.SCRAMJET].globalProxy;
return self.parent.self[SCRAMJETCLIENT].globalProxy;
} else {
// ... then we should pretend we aren't nested and return the current window
return client.globalProxy;
@ -31,13 +32,13 @@ export default function (client: ScramjetClient, self: typeof globalThis) {
if (test === current) break; // there is no parent, actual or emulated.
// ... then `test` represents a window outside of the proxy context, and therefore `current` is the topmost window in the proxy context
if (!(ScramjetClient.SCRAMJET in test)) break;
if (!(SCRAMJETCLIENT in test)) break;
// test is also insde a proxy, so we should continue up the chain
current = test;
}
return current[ScramjetClient.SCRAMJET].globalProxy.window;
return current[SCRAMJETCLIENT].globalProxy.window;
} else if (
(iswindow && identifier instanceof self.Location) ||
(isworker && identifier instanceof self.WorkerLocation)
@ -89,7 +90,7 @@ export default function (client: ScramjetClient, self: typeof globalThis) {
}
}
self.$scramerr = function scramerr(e) {
// console.warn("CAUGHT ERROR", e);
console.warn("CAUGHT ERROR", e);
};
self.$scramdbg = function scramdbg(args, t) {

33
src/controller/frame.ts Normal file
View file

@ -0,0 +1,33 @@
import { ScramjetController } from ".";
import type { ScramjetClient } from "../client/client";
import { SCRAMJETCLIENT, SCRAMJETFRAME } from "../symbols";
export class ScramjetFrame extends EventTarget {
constructor(
private controller: ScramjetController,
public frame: HTMLIFrameElement
) {
super();
frame[SCRAMJETFRAME] = this;
}
get client(): ScramjetClient {
return this.frame.contentWindow.window[SCRAMJETCLIENT];
}
go(url: string | URL) {
if (url instanceof URL) url = url.toString();
dbg.log("navigated to", url);
this.frame.src = this.controller.encodeUrl(url);
}
back() {
this.frame.contentWindow?.history.back();
}
forward() {
this.frame.contentWindow?.history.forward();
}
}

View file

@ -1,6 +1,8 @@
import IDBMap from "@webreflection/idb-map";
import { ScramjetConfig } from "../types";
import { Codec } from "../codecs";
import type { ScramjetClient } from "../client/client";
import { ScramjetFrame } from "./frame";
export class ScramjetController {
config: ScramjetConfig;
@ -24,7 +26,7 @@ export class ScramjetController {
client: "/scramjet.client.js",
codecs: "/scramjet.codecs.js",
flags: {
serviceworkers: true,
serviceworkers: false,
},
};
@ -74,31 +76,4 @@ export class ScramjetController {
}
}
class ScramjetFrame extends EventTarget {
static SCRAMJETFRAME = Symbol.for("scramjet frame handle");
constructor(
private controller: ScramjetController,
public frame: HTMLIFrameElement
) {
super();
frame[ScramjetFrame.SCRAMJETFRAME] = this;
}
go(url: string | URL) {
if (url instanceof URL) url = url.toString();
dbg.log("navigated to", url);
this.frame.src = this.controller.encodeUrl(url);
}
back() {
this.frame.contentWindow?.history.back();
}
forward() {
this.frame.contentWindow?.history.forward();
}
}
window.ScramjetController = ScramjetController;

View file

@ -150,6 +150,12 @@ export const htmlRules: {
fn: (value: string, origin?: URL) => rewriteCss(value, origin),
style: "*",
},
{
fn: (value: string) => {
if (["_parent", "_top", "_unfencedTop"].includes(value)) return "_self";
},
target: ["a"],
},
];
// i need to add the attributes in during rewriting

3
src/symbols.ts Normal file
View file

@ -0,0 +1,3 @@
// see types.d.ts for what these mean
export const SCRAMJETCLIENT = Symbol.for("scramjet client global");
export const SCRAMJETFRAME = Symbol.for("scramjet frame handle");

11
src/types.d.ts vendored
View file

@ -15,6 +15,9 @@ import { BareClient } from "@mercuryworkshop/bare-mux";
import { parseDomain } from "parse-domain";
import { ScramjetHeaders } from "./shared/headers";
import { CookieStore } from "./shared/cookie";
import { SCRAMJETCLIENT, SCRAMJETFRAME } from "./symbols";
import { ScramjetClient } from "./client/client";
import { ScramjetFrame } from "./controller/frame";
type ScramjetFlags = {
serviceworkers: boolean;
@ -75,5 +78,13 @@ declare global {
COOKIE: string;
WASM: string;
ScramjetController: typeof ScramjetController;
// the scramjet client belonging to a window
[SCRAMJETCLIENT]: ScramjetClient;
}
interface HTMLIFrameElement {
// the event target belonging to an <iframe> holding a /prefix/blah url
[SCRAMJETFRAME]: ScramjetFrame;
}
}