mirror of
https://github.com/MercuryWorkshop/scramjet.git
synced 2025-05-12 22:10:01 -04:00
return real window.parent
This commit is contained in:
parent
396170e4ea
commit
b0f5166916
4 changed files with 62 additions and 38 deletions
|
@ -1,7 +1,8 @@
|
||||||
import { encodeUrl } from "../shared";
|
import { encodeUrl } from "../shared";
|
||||||
|
import { importfn } from "./wrap";
|
||||||
|
|
||||||
export default function (client, self) {
|
export default function (client, self) {
|
||||||
self.$sImport = function (base) {
|
self[importfn] = function (base) {
|
||||||
return function (url) {
|
return function (url) {
|
||||||
const resolved = new URL(url, base).href;
|
const resolved = new URL(url, base).href;
|
||||||
|
|
||||||
|
|
|
@ -14,40 +14,65 @@ export default function (client: ScramjetClient, self: typeof globalThis) {
|
||||||
// the main magic of the proxy. all attempts to access any "banned objects" will be redirected here, and instead served a proxy object
|
// the main magic of the proxy. all attempts to access any "banned objects" will be redirected here, and instead served a proxy object
|
||||||
// this contrasts from how other proxies will leave the root object alone and instead attempt to catch every member access
|
// this contrasts from how other proxies will leave the root object alone and instead attempt to catch every member access
|
||||||
// this presents some issues (see element.ts), but makes us a good bit faster at runtime!
|
// this presents some issues (see element.ts), but makes us a good bit faster at runtime!
|
||||||
|
Object.defineProperty(self, wrapfn, {
|
||||||
|
value: function (identifier: any) {
|
||||||
|
if (iswindow && identifier instanceof self.Window) {
|
||||||
|
return client.windowProxy;
|
||||||
|
} else if (iswindow && identifier instanceof self.parent.self.Window) {
|
||||||
|
if (ScramjetClient.SCRAMJET 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].windowProxy;
|
||||||
|
} else {
|
||||||
|
// ... then we should pretend we aren't nested and return the current window
|
||||||
|
return client.windowProxy;
|
||||||
|
}
|
||||||
|
} else if (iswindow && identifier instanceof self.top.self.Window) {
|
||||||
|
// instead of returning top, we need to return the uppermost parent that's inside a scramjet context
|
||||||
|
let current = self.self;
|
||||||
|
|
||||||
self[wrapfn] = function (identifier: any) {
|
for (;;) {
|
||||||
if (
|
const test = current.parent.self;
|
||||||
iswindow &&
|
if (test === current) break; // there is no parent, actual or emulated.
|
||||||
(identifier instanceof self.Window ||
|
|
||||||
identifier instanceof self.top.window.Window ||
|
|
||||||
identifier instanceof self.parent.window.Window)
|
|
||||||
) {
|
|
||||||
// this will break iframe postmessage!
|
|
||||||
return client.windowProxy;
|
|
||||||
} else if (
|
|
||||||
(iswindow && identifier instanceof Location) ||
|
|
||||||
(isworker && identifier instanceof WorkerLocation)
|
|
||||||
) {
|
|
||||||
return client.locationProxy;
|
|
||||||
} else if (iswindow && identifier instanceof Document) {
|
|
||||||
return client.documentProxy;
|
|
||||||
} else if (isworker && identifier instanceof WorkerGlobalScope) {
|
|
||||||
return client.windowProxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
return identifier;
|
// ... 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;
|
||||||
|
|
||||||
|
// test is also insde a proxy, so we should continue up the chain
|
||||||
|
current = test;
|
||||||
|
}
|
||||||
|
|
||||||
|
return current[ScramjetClient.SCRAMJET].windowProxy;
|
||||||
|
} else if (
|
||||||
|
(iswindow && identifier instanceof self.Location) ||
|
||||||
|
(isworker && identifier instanceof self.WorkerLocation)
|
||||||
|
) {
|
||||||
|
return client.locationProxy;
|
||||||
|
} else if (iswindow && identifier instanceof self.Document) {
|
||||||
|
return client.documentProxy;
|
||||||
|
} else if (isworker && identifier instanceof self.WorkerGlobalScope) {
|
||||||
|
return client.windowProxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
return identifier;
|
||||||
|
},
|
||||||
|
writable: false,
|
||||||
|
configurable: false,
|
||||||
|
});
|
||||||
|
|
||||||
// location = "..." can't be rewritten as wrapfn(location) = ..., so instead it will actually be rewritten as
|
// location = "..." can't be rewritten as wrapfn(location) = ..., so instead it will actually be rewritten as
|
||||||
// ((t)=>$scramjet$tryset(location,"+=",t)||location+=t)(...);
|
// ((t)=>$scramjet$tryset(location,"+=",t)||location+=t)(...);
|
||||||
// it has to be a discrete function because there's always the possibility that "location" is a local variable
|
// it has to be a discrete function because there's always the possibility that "location" is a local variable
|
||||||
// we have to use an IIFE to avoid duplicating side-effects in the getter
|
// we have to use an IIFE to avoid duplicating side-effects in the getter
|
||||||
self[trysetfn] = function (lhs: any, op: string, rhs: any) {
|
Object.defineProperty(self, trysetfn, {
|
||||||
if (lhs instanceof Location) {
|
value: function (lhs: any, op: string, rhs: any) {
|
||||||
// @ts-ignore
|
if (lhs instanceof Location) {
|
||||||
locationProxy.href = rhs;
|
// @ts-ignore
|
||||||
|
locationProxy.href = rhs;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
writable: false,
|
||||||
|
configurable: false,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { encodeUrl } from "../shared/rewriters/url";
|
import { encodeUrl } from "../shared/rewriters/url";
|
||||||
import { ScramjetClient } from "./client";
|
import { ScramjetClient } from "./client";
|
||||||
|
import { wrapfn } from "./shared/wrap";
|
||||||
|
|
||||||
export function createWindowProxy(
|
export function createWindowProxy(
|
||||||
client: ScramjetClient,
|
client: ScramjetClient,
|
||||||
|
@ -12,11 +13,9 @@ export function createWindowProxy(
|
||||||
return client.locationProxy;
|
return client.locationProxy;
|
||||||
} else if (
|
} else if (
|
||||||
propIsString &&
|
propIsString &&
|
||||||
["window", "top", "self", "globalThis"].includes(prop)
|
["window", "top", "self", "globalThis", "parent"].includes(prop)
|
||||||
) {
|
) {
|
||||||
return client.windowProxy;
|
return self[wrapfn](self[prop]);
|
||||||
} else if (propIsString && prop == "parent") {
|
|
||||||
return self.parent;
|
|
||||||
} else if (propIsString && prop === "$scramjet") {
|
} else if (propIsString && prop === "$scramjet") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import {
|
||||||
rewrite_js_from_arraybuffer,
|
rewrite_js_from_arraybuffer,
|
||||||
} from "../../../rewriter/out/rewriter.js";
|
} from "../../../rewriter/out/rewriter.js";
|
||||||
import "../../../static/wasm.js";
|
import "../../../static/wasm.js";
|
||||||
import { importfn, wrapfn } from "../../client/shared/wrap";
|
|
||||||
|
|
||||||
initSync(
|
initSync(
|
||||||
new WebAssembly.Module(
|
new WebAssembly.Module(
|
||||||
|
@ -32,8 +31,8 @@ export function rewriteJs(js: string | ArrayBuffer, origin?: URL) {
|
||||||
origin.toString(),
|
origin.toString(),
|
||||||
self.$scramjet.config.prefix,
|
self.$scramjet.config.prefix,
|
||||||
self.$scramjet.config.codec.encode as any,
|
self.$scramjet.config.codec.encode as any,
|
||||||
wrapfn,
|
"$scramjet$wrap",
|
||||||
importfn
|
"$scramjet$import"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -42,8 +41,8 @@ export function rewriteJs(js: string | ArrayBuffer, origin?: URL) {
|
||||||
origin.toString(),
|
origin.toString(),
|
||||||
self.$scramjet.config.prefix,
|
self.$scramjet.config.prefix,
|
||||||
self.$scramjet.config.codec.encode as any,
|
self.$scramjet.config.codec.encode as any,
|
||||||
wrapfn,
|
"$scramjet$wrap",
|
||||||
importfn
|
"$scramjet$import"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const after = performance.now();
|
const after = performance.now();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue