mirror of
https://github.com/MercuryWorkshop/scramjet.git
synced 2025-05-13 06:20:02 -04:00
ScramjetClient.SCRAMJET -> SCRAMJETCLIENT
This commit is contained in:
parent
2050fa140c
commit
5f77342d8d
11 changed files with 82 additions and 50 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
import { SCRAMJETCLIENT } from "../symbols";
|
||||||
import { createDocumentProxy } from "./document";
|
import { createDocumentProxy } from "./document";
|
||||||
import { createGlobalProxy } from "./global";
|
import { createGlobalProxy } from "./global";
|
||||||
import { getOwnPropertyDescriptorHandler } from "./helpers";
|
import { getOwnPropertyDescriptorHandler } from "./helpers";
|
||||||
|
@ -43,8 +44,6 @@ export type Trap<T> = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export class ScramjetClient {
|
export class ScramjetClient {
|
||||||
static SCRAMJET = Symbol.for("scramjet client global");
|
|
||||||
|
|
||||||
documentProxy: any;
|
documentProxy: any;
|
||||||
globalProxy: any;
|
globalProxy: any;
|
||||||
locationProxy: any;
|
locationProxy: any;
|
||||||
|
@ -76,7 +75,7 @@ export class ScramjetClient {
|
||||||
this.locationProxy = createLocationProxy(this, global);
|
this.locationProxy = createLocationProxy(this, global);
|
||||||
this.globalProxy = createGlobalProxy(this, global);
|
this.globalProxy = createGlobalProxy(this, global);
|
||||||
|
|
||||||
global[ScramjetClient.SCRAMJET] = this;
|
global[SCRAMJETCLIENT] = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
loadcookies(cookiestr: string) {
|
loadcookies(cookiestr: string) {
|
||||||
|
@ -175,6 +174,7 @@ export class ScramjetClient {
|
||||||
if (handler.apply) {
|
if (handler.apply) {
|
||||||
h.apply = function (fn: any, thisArg: any, argArray: any[]) {
|
h.apply = function (fn: any, thisArg: any, argArray: any[]) {
|
||||||
let returnValue: any = null;
|
let returnValue: any = null;
|
||||||
|
let earlyreturn = false;
|
||||||
|
|
||||||
const ctx: ProxyCtx = {
|
const ctx: ProxyCtx = {
|
||||||
fn,
|
fn,
|
||||||
|
@ -182,6 +182,7 @@ export class ScramjetClient {
|
||||||
args: argArray,
|
args: argArray,
|
||||||
newTarget: null,
|
newTarget: null,
|
||||||
return: (r: any) => {
|
return: (r: any) => {
|
||||||
|
earlyreturn = true;
|
||||||
returnValue = r;
|
returnValue = r;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -213,7 +214,7 @@ export class ScramjetClient {
|
||||||
|
|
||||||
delete Error.prepareStackTrace;
|
delete Error.prepareStackTrace;
|
||||||
|
|
||||||
if (returnValue) {
|
if (earlyreturn) {
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { SCRAMJETCLIENT } from "../../symbols";
|
||||||
import { ScramjetClient } from "../client";
|
import { ScramjetClient } from "../client";
|
||||||
import { nativeGetOwnPropertyDescriptor } from "../natives";
|
import { nativeGetOwnPropertyDescriptor } from "../natives";
|
||||||
import { config, decodeUrl, htmlRules, unrewriteHtml } from "../shared";
|
import { config, decodeUrl, htmlRules, unrewriteHtml } from "../shared";
|
||||||
|
@ -127,8 +128,8 @@ export default function (client: ScramjetClient, self: typeof window) {
|
||||||
get(ctx) {
|
get(ctx) {
|
||||||
const realwin = ctx.get() as Window;
|
const realwin = ctx.get() as Window;
|
||||||
|
|
||||||
if (ScramjetClient.SCRAMJET in realwin.self) {
|
if (SCRAMJETCLIENT in realwin.self) {
|
||||||
return realwin.self[ScramjetClient.SCRAMJET].globalProxy.window;
|
return realwin.self[SCRAMJETCLIENT].globalProxy.window;
|
||||||
} else {
|
} else {
|
||||||
// hook the iframe
|
// hook the iframe
|
||||||
const newclient = new ScramjetClient(realwin.self);
|
const newclient = new ScramjetClient(realwin.self);
|
||||||
|
@ -145,8 +146,8 @@ export default function (client: ScramjetClient, self: typeof window) {
|
||||||
client.descriptors["HTMLIFrameElement.prototype.contentWindow"].get;
|
client.descriptors["HTMLIFrameElement.prototype.contentWindow"].get;
|
||||||
const realwin = contentwindow.apply(ctx.this);
|
const realwin = contentwindow.apply(ctx.this);
|
||||||
|
|
||||||
if (ScramjetClient.SCRAMJET in realwin.self) {
|
if (SCRAMJETCLIENT in realwin.self) {
|
||||||
return realwin.self[ScramjetClient.SCRAMJET].documentProxy;
|
return realwin.self[SCRAMJETCLIENT].documentProxy;
|
||||||
} else {
|
} else {
|
||||||
const newclient = new ScramjetClient(realwin.self);
|
const newclient = new ScramjetClient(realwin.self);
|
||||||
newclient.hook();
|
newclient.hook();
|
||||||
|
@ -175,7 +176,7 @@ export default function (client: ScramjetClient, self: typeof window) {
|
||||||
let doc = ctx.get() as Document | null;
|
let doc = ctx.get() as Document | null;
|
||||||
if (!doc) return null;
|
if (!doc) return null;
|
||||||
|
|
||||||
let scram: ScramjetClient = doc[ScramjetClient.SCRAMJET];
|
let scram: ScramjetClient = doc[SCRAMJETCLIENT];
|
||||||
if (!scram) return doc; // ??
|
if (!scram) return doc; // ??
|
||||||
|
|
||||||
return scram.documentProxy;
|
return scram.documentProxy;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { encodeUrl } from "../shared";
|
import { encodeUrl } from "../shared";
|
||||||
import { ScramjetClient } from "../client";
|
import { ScramjetClient } from "../client";
|
||||||
|
import { SCRAMJETCLIENT } from "../../symbols";
|
||||||
|
|
||||||
export default function (client: ScramjetClient) {
|
export default function (client: ScramjetClient) {
|
||||||
client.Proxy("window.open", {
|
client.Proxy("window.open", {
|
||||||
|
@ -13,10 +14,8 @@ export default function (client: ScramjetClient) {
|
||||||
|
|
||||||
if (!realwin) return ctx.return(realwin);
|
if (!realwin) return ctx.return(realwin);
|
||||||
|
|
||||||
if (ScramjetClient.SCRAMJET in realwin.self) {
|
if (SCRAMJETCLIENT in realwin.self) {
|
||||||
return ctx.return(
|
return ctx.return(realwin.self[SCRAMJETCLIENT].globalProxy.window);
|
||||||
realwin.self[ScramjetClient.SCRAMJET].globalProxy.window
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
const newclient = new ScramjetClient(realwin.self);
|
const newclient = new ScramjetClient(realwin.self);
|
||||||
// hook the opened window
|
// hook the opened window
|
||||||
|
@ -32,8 +31,8 @@ export default function (client: ScramjetClient) {
|
||||||
get(ctx) {
|
get(ctx) {
|
||||||
const realwin = ctx.get() as Window;
|
const realwin = ctx.get() as Window;
|
||||||
|
|
||||||
if (realwin && ScramjetClient.SCRAMJET in realwin.self) {
|
if (realwin && SCRAMJETCLIENT in realwin.self) {
|
||||||
return realwin.self[ScramjetClient.SCRAMJET].globalProxy;
|
return realwin.self[SCRAMJETCLIENT].globalProxy;
|
||||||
} else {
|
} else {
|
||||||
// the opener has to have been already hooked, so if we reach here then it's a real window
|
// the opener has to have been already hooked, so if we reach here then it's a real window
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// entrypoint for scramjet.client.js
|
// entrypoint for scramjet.client.js
|
||||||
|
|
||||||
|
import { SCRAMJETCLIENT } from "../symbols";
|
||||||
import { ScramjetClient } from "./client";
|
import { ScramjetClient } from "./client";
|
||||||
import { ScramjetServiceWorkerRuntime } from "./swruntime";
|
import { ScramjetServiceWorkerRuntime } from "./swruntime";
|
||||||
|
|
||||||
|
@ -13,7 +14,7 @@ export const isemulatedsw =
|
||||||
|
|
||||||
dbg.log("scrammin");
|
dbg.log("scrammin");
|
||||||
// if it already exists, that means the handlers have probably already been setup by the parent document
|
// 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);
|
const client = new ScramjetClient(self);
|
||||||
|
|
||||||
if (self.COOKIE) client.loadcookies(self.COOKIE);
|
if (self.COOKIE) client.loadcookies(self.COOKIE);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { iswindow } from "..";
|
import { iswindow } from "..";
|
||||||
|
import { SCRAMJETCLIENT } from "../../symbols";
|
||||||
import { ScramjetClient } from "../client";
|
import { ScramjetClient } from "../client";
|
||||||
import { getOwnPropertyDescriptorHandler } from "../helpers";
|
import { getOwnPropertyDescriptorHandler } from "../helpers";
|
||||||
import { nativeGetOwnPropertyDescriptor } from "../natives";
|
import { nativeGetOwnPropertyDescriptor } from "../natives";
|
||||||
|
@ -22,7 +23,7 @@ export default function (client: ScramjetClient, self: Self) {
|
||||||
return this.ports;
|
return this.ports;
|
||||||
},
|
},
|
||||||
source() {
|
source() {
|
||||||
let scram: ScramjetClient = this.source[ScramjetClient.SCRAMJET];
|
let scram: ScramjetClient = this.source[SCRAMJETCLIENT];
|
||||||
|
|
||||||
if (scram) return scram.globalProxy;
|
if (scram) return scram.globalProxy;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { iswindow, isworker } from "..";
|
import { iswindow, isworker } from "..";
|
||||||
|
import { SCRAMJETCLIENT } from "../../symbols";
|
||||||
import { ScramjetClient } from "../client";
|
import { ScramjetClient } from "../client";
|
||||||
import { config } from "../shared";
|
import { config } from "../shared";
|
||||||
|
|
||||||
|
@ -15,9 +16,9 @@ export default function (client: ScramjetClient, self: typeof globalThis) {
|
||||||
if (iswindow && identifier instanceof self.Window) {
|
if (iswindow && identifier instanceof self.Window) {
|
||||||
return client.globalProxy;
|
return client.globalProxy;
|
||||||
} else if (iswindow && identifier instanceof self.parent.self.Window) {
|
} 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
|
// ... 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 {
|
} else {
|
||||||
// ... then we should pretend we aren't nested and return the current window
|
// ... then we should pretend we aren't nested and return the current window
|
||||||
return client.globalProxy;
|
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.
|
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
|
// ... 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
|
// test is also insde a proxy, so we should continue up the chain
|
||||||
current = test;
|
current = test;
|
||||||
}
|
}
|
||||||
|
|
||||||
return current[ScramjetClient.SCRAMJET].globalProxy.window;
|
return current[SCRAMJETCLIENT].globalProxy.window;
|
||||||
} else if (
|
} else if (
|
||||||
(iswindow && identifier instanceof self.Location) ||
|
(iswindow && identifier instanceof self.Location) ||
|
||||||
(isworker && identifier instanceof self.WorkerLocation)
|
(isworker && identifier instanceof self.WorkerLocation)
|
||||||
|
@ -89,7 +90,7 @@ export default function (client: ScramjetClient, self: typeof globalThis) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.$scramerr = function scramerr(e) {
|
self.$scramerr = function scramerr(e) {
|
||||||
// console.warn("CAUGHT ERROR", e);
|
console.warn("CAUGHT ERROR", e);
|
||||||
};
|
};
|
||||||
|
|
||||||
self.$scramdbg = function scramdbg(args, t) {
|
self.$scramdbg = function scramdbg(args, t) {
|
||||||
|
|
33
src/controller/frame.ts
Normal file
33
src/controller/frame.ts
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
import IDBMap from "@webreflection/idb-map";
|
import IDBMap from "@webreflection/idb-map";
|
||||||
import { ScramjetConfig } from "../types";
|
import { ScramjetConfig } from "../types";
|
||||||
import { Codec } from "../codecs";
|
import { Codec } from "../codecs";
|
||||||
|
import type { ScramjetClient } from "../client/client";
|
||||||
|
import { ScramjetFrame } from "./frame";
|
||||||
|
|
||||||
export class ScramjetController {
|
export class ScramjetController {
|
||||||
config: ScramjetConfig;
|
config: ScramjetConfig;
|
||||||
|
@ -24,7 +26,7 @@ export class ScramjetController {
|
||||||
client: "/scramjet.client.js",
|
client: "/scramjet.client.js",
|
||||||
codecs: "/scramjet.codecs.js",
|
codecs: "/scramjet.codecs.js",
|
||||||
flags: {
|
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;
|
window.ScramjetController = ScramjetController;
|
||||||
|
|
|
@ -150,6 +150,12 @@ export const htmlRules: {
|
||||||
fn: (value: string, origin?: URL) => rewriteCss(value, origin),
|
fn: (value: string, origin?: URL) => rewriteCss(value, origin),
|
||||||
style: "*",
|
style: "*",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
fn: (value: string) => {
|
||||||
|
if (["_parent", "_top", "_unfencedTop"].includes(value)) return "_self";
|
||||||
|
},
|
||||||
|
target: ["a"],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// i need to add the attributes in during rewriting
|
// i need to add the attributes in during rewriting
|
||||||
|
|
3
src/symbols.ts
Normal file
3
src/symbols.ts
Normal 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
11
src/types.d.ts
vendored
|
@ -15,6 +15,9 @@ import { BareClient } from "@mercuryworkshop/bare-mux";
|
||||||
import { parseDomain } from "parse-domain";
|
import { parseDomain } from "parse-domain";
|
||||||
import { ScramjetHeaders } from "./shared/headers";
|
import { ScramjetHeaders } from "./shared/headers";
|
||||||
import { CookieStore } from "./shared/cookie";
|
import { CookieStore } from "./shared/cookie";
|
||||||
|
import { SCRAMJETCLIENT, SCRAMJETFRAME } from "./symbols";
|
||||||
|
import { ScramjetClient } from "./client/client";
|
||||||
|
import { ScramjetFrame } from "./controller/frame";
|
||||||
|
|
||||||
type ScramjetFlags = {
|
type ScramjetFlags = {
|
||||||
serviceworkers: boolean;
|
serviceworkers: boolean;
|
||||||
|
@ -75,5 +78,13 @@ declare global {
|
||||||
COOKIE: string;
|
COOKIE: string;
|
||||||
WASM: string;
|
WASM: string;
|
||||||
ScramjetController: typeof ScramjetController;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue