mirror of
https://github.com/MercuryWorkshop/scramjet.git
synced 2025-05-13 06:20:02 -04:00
implement direct and indirect eval
This commit is contained in:
parent
e6b237c525
commit
ec8421be8f
12 changed files with 171 additions and 101 deletions
|
@ -2,8 +2,8 @@ pub mod rewrite;
|
||||||
|
|
||||||
use std::{panic, str::FromStr};
|
use std::{panic, str::FromStr};
|
||||||
|
|
||||||
use js_sys::Function;
|
use js_sys::{Function, Object, Reflect};
|
||||||
use rewrite::{rewrite, EncodeFn};
|
use rewrite::{rewrite, Config, EncodeFn};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
@ -30,42 +30,58 @@ fn create_encode_function(encode: Function) -> EncodeFn {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn rewrite_js(
|
pub fn rewrite_js(js: &str, url: &str, config: Object) -> Vec<u8> {
|
||||||
js: &str,
|
|
||||||
url: &str,
|
|
||||||
prefix: String,
|
|
||||||
encode: Function,
|
|
||||||
wrapfn: String,
|
|
||||||
importfn: String,
|
|
||||||
) -> Vec<u8> {
|
|
||||||
rewrite(
|
rewrite(
|
||||||
js,
|
js,
|
||||||
Url::from_str(url).unwrap(),
|
Url::from_str(url).unwrap(),
|
||||||
prefix,
|
Config {
|
||||||
create_encode_function(encode),
|
prefix: Reflect::get(&config, &"prefix".into())
|
||||||
wrapfn,
|
.unwrap()
|
||||||
importfn,
|
.as_string()
|
||||||
|
.unwrap(),
|
||||||
|
encode: create_encode_function(Reflect::get(&config, &"encode".into()).unwrap().into()),
|
||||||
|
wrapfn: Reflect::get(&config, &"wrapfn".into())
|
||||||
|
.unwrap()
|
||||||
|
.as_string()
|
||||||
|
.unwrap(),
|
||||||
|
importfn: Reflect::get(&config, &"importfn".into())
|
||||||
|
.unwrap()
|
||||||
|
.as_string()
|
||||||
|
.unwrap(),
|
||||||
|
rewritefn: Reflect::get(&config, &"rewritefn".into())
|
||||||
|
.unwrap()
|
||||||
|
.as_string()
|
||||||
|
.unwrap(),
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn rewrite_js_from_arraybuffer(
|
pub fn rewrite_js_from_arraybuffer(js: &[u8], url: &str, config: Object) -> Vec<u8> {
|
||||||
js: &[u8],
|
|
||||||
url: &str,
|
|
||||||
prefix: String,
|
|
||||||
encode: Function,
|
|
||||||
wrapfn: String,
|
|
||||||
importfn: String,
|
|
||||||
) -> Vec<u8> {
|
|
||||||
// we know that this is a valid utf-8 string
|
// we know that this is a valid utf-8 string
|
||||||
let js = unsafe { std::str::from_utf8_unchecked(js) };
|
let js = unsafe { std::str::from_utf8_unchecked(js) };
|
||||||
|
|
||||||
rewrite(
|
rewrite(
|
||||||
js,
|
js,
|
||||||
Url::from_str(url).unwrap(),
|
Url::from_str(url).unwrap(),
|
||||||
prefix,
|
Config {
|
||||||
create_encode_function(encode),
|
prefix: Reflect::get(&config, &"prefix".into())
|
||||||
wrapfn,
|
.unwrap()
|
||||||
importfn,
|
.as_string()
|
||||||
|
.unwrap(),
|
||||||
|
encode: create_encode_function(Reflect::get(&config, &"encode".into()).unwrap().into()),
|
||||||
|
wrapfn: Reflect::get(&config, &"wrapfn".into())
|
||||||
|
.unwrap()
|
||||||
|
.as_string()
|
||||||
|
.unwrap(),
|
||||||
|
importfn: Reflect::get(&config, &"importfn".into())
|
||||||
|
.unwrap()
|
||||||
|
.as_string()
|
||||||
|
.unwrap(),
|
||||||
|
rewritefn: Reflect::get(&config, &"rewritefn".into())
|
||||||
|
.unwrap()
|
||||||
|
.as_string()
|
||||||
|
.unwrap(),
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ pub mod rewrite;
|
||||||
use rewrite::rewrite;
|
use rewrite::rewrite;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
use crate::rewrite::Config;
|
||||||
|
|
||||||
// Instruction:
|
// Instruction:
|
||||||
// create a `test.js`,
|
// create a `test.js`,
|
||||||
// run `cargo run -p oxc_parser --example visitor`
|
// run `cargo run -p oxc_parser --example visitor`
|
||||||
|
@ -112,10 +114,13 @@ fn main() -> std::io::Result<()> {
|
||||||
rewrite(
|
rewrite(
|
||||||
&source_text,
|
&source_text,
|
||||||
Url::from_str("https://google.com/glorngle/si.js").unwrap(),
|
Url::from_str("https://google.com/glorngle/si.js").unwrap(),
|
||||||
"/scrammedjet/".to_string(),
|
Config {
|
||||||
Box::new(encode_string),
|
prefix: "/scrammedjet/".to_string(),
|
||||||
"$wrap".to_string(),
|
encode: Box::new(encode_string),
|
||||||
"$import".to_string(),
|
wrapfn: "$wrap".to_string(),
|
||||||
|
importfn: "$import".to_string(),
|
||||||
|
rewritefn: "$rewrite".to_string(),
|
||||||
|
}
|
||||||
)
|
)
|
||||||
.as_slice()
|
.as_slice()
|
||||||
)
|
)
|
||||||
|
|
|
@ -30,18 +30,24 @@ pub type EncodeFn = Box<dyn Fn(String) -> String>;
|
||||||
struct Rewriter {
|
struct Rewriter {
|
||||||
jschanges: Vec<JsChange>,
|
jschanges: Vec<JsChange>,
|
||||||
base: Url,
|
base: Url,
|
||||||
prefix: String,
|
config: Config,
|
||||||
wrapfn: String,
|
|
||||||
importfn: String,
|
|
||||||
encode: EncodeFn,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Config {
|
||||||
|
pub prefix: String,
|
||||||
|
pub wrapfn: String,
|
||||||
|
pub importfn: String,
|
||||||
|
pub rewritefn: String,
|
||||||
|
pub encode: EncodeFn,
|
||||||
|
}
|
||||||
|
|
||||||
impl Rewriter {
|
impl Rewriter {
|
||||||
fn rewrite_url(&mut self, url: String) -> String {
|
fn rewrite_url(&mut self, url: String) -> String {
|
||||||
let url = self.base.join(&url).unwrap();
|
let url = self.base.join(&url).unwrap();
|
||||||
|
|
||||||
let urlencoded = (self.encode)(url.to_string());
|
let urlencoded = (self.config.encode)(url.to_string());
|
||||||
|
|
||||||
format!("\"{}{}\"", self.prefix, urlencoded)
|
format!("\"{}{}\"", self.config.prefix, urlencoded)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,24 +63,49 @@ impl<'a> Visit<'a> for Rewriter {
|
||||||
if UNSAFE_GLOBALS.contains(&it.name.to_string().as_str()) {
|
if UNSAFE_GLOBALS.contains(&it.name.to_string().as_str()) {
|
||||||
self.jschanges.push(JsChange::GenericChange {
|
self.jschanges.push(JsChange::GenericChange {
|
||||||
span: it.span,
|
span: it.span,
|
||||||
text: format!("({}({}))", self.wrapfn, it.name),
|
text: format!("({}({}))", self.config.wrapfn, it.name),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn visit_this_expression(&mut self, it: &oxc_ast::ast::ThisExpression) {
|
fn visit_this_expression(&mut self, it: &oxc_ast::ast::ThisExpression) {
|
||||||
self.jschanges.push(JsChange::GenericChange {
|
self.jschanges.push(JsChange::GenericChange {
|
||||||
span: it.span,
|
span: it.span,
|
||||||
text: format!("({}(this))", self.wrapfn),
|
text: format!("({}(this))", self.config.wrapfn),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_debugger_statement(&mut self, it: &oxc_ast::ast::DebuggerStatement) {
|
fn visit_debugger_statement(&mut self, it: &oxc_ast::ast::DebuggerStatement) {
|
||||||
|
// delete debugger statements entirely. some sites will spam debugger as an anti-debugging measure, and we don't want that!
|
||||||
self.jschanges.push(JsChange::GenericChange {
|
self.jschanges.push(JsChange::GenericChange {
|
||||||
span: it.span,
|
span: it.span,
|
||||||
text: "".to_string(),
|
text: "".to_string(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we can't overwrite window.eval in the normal way because that would make everything an
|
||||||
|
// indirect eval, which could break things. we handle that edge case here
|
||||||
|
fn visit_call_expression(&mut self, it: &oxc_ast::ast::CallExpression<'a>) {
|
||||||
|
if let Expression::Identifier(s) = &it.callee {
|
||||||
|
// if it's optional that actually makes it an indirect eval which is handled separately
|
||||||
|
if s.name == "eval" && !it.optional {
|
||||||
|
self.jschanges.push(JsChange::GenericChange {
|
||||||
|
span: Span::new(s.span.start, s.span.end + 1),
|
||||||
|
text: format!("eval({}(", self.config.rewritefn),
|
||||||
|
});
|
||||||
|
self.jschanges.push(JsChange::GenericChange {
|
||||||
|
span: Span::new(it.span.end, it.span.end),
|
||||||
|
text: ")".to_string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
// then we walk the arguments, but not the callee, since we want it to resolve to
|
||||||
|
// the real eval
|
||||||
|
walk::walk_arguments(self, &it.arguments);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
walk::walk_call_expression(self, it);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_import_declaration(&mut self, it: &oxc_ast::ast::ImportDeclaration<'a>) {
|
fn visit_import_declaration(&mut self, it: &oxc_ast::ast::ImportDeclaration<'a>) {
|
||||||
let name = it.source.value.to_string();
|
let name = it.source.value.to_string();
|
||||||
let text = self.rewrite_url(name);
|
let text = self.rewrite_url(name);
|
||||||
|
@ -87,7 +118,7 @@ impl<'a> Visit<'a> for Rewriter {
|
||||||
fn visit_import_expression(&mut self, it: &oxc_ast::ast::ImportExpression<'a>) {
|
fn visit_import_expression(&mut self, it: &oxc_ast::ast::ImportExpression<'a>) {
|
||||||
self.jschanges.push(JsChange::GenericChange {
|
self.jschanges.push(JsChange::GenericChange {
|
||||||
span: Span::new(it.span.start, it.span.start + 6),
|
span: Span::new(it.span.start, it.span.start + 6),
|
||||||
text: format!("({}(\"{}\"))", self.importfn, self.base),
|
text: format!("({}(\"{}\"))", self.config.importfn, self.base),
|
||||||
});
|
});
|
||||||
walk::walk_import_expression(self, it);
|
walk::walk_import_expression(self, it);
|
||||||
}
|
}
|
||||||
|
@ -122,7 +153,7 @@ impl<'a> Visit<'a> for Rewriter {
|
||||||
if UNSAFE_GLOBALS.contains(&s.name.to_string().as_str()) && p.shorthand {
|
if UNSAFE_GLOBALS.contains(&s.name.to_string().as_str()) && p.shorthand {
|
||||||
self.jschanges.push(JsChange::GenericChange {
|
self.jschanges.push(JsChange::GenericChange {
|
||||||
span: s.span,
|
span: s.span,
|
||||||
text: format!("{}: ({}({}))", s.name, self.wrapfn, s.name),
|
text: format!("{}: ({}({}))", s.name, self.config.wrapfn, s.name),
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -238,7 +269,7 @@ fn expression_span(e: &Expression) -> Span {
|
||||||
}
|
}
|
||||||
|
|
||||||
// js MUST not be able to get a reference to any of these because sbx
|
// js MUST not be able to get a reference to any of these because sbx
|
||||||
const UNSAFE_GLOBALS: [&str; 8] = [
|
const UNSAFE_GLOBALS: [&str; 9] = [
|
||||||
"window",
|
"window",
|
||||||
"self",
|
"self",
|
||||||
"globalThis",
|
"globalThis",
|
||||||
|
@ -247,16 +278,10 @@ const UNSAFE_GLOBALS: [&str; 8] = [
|
||||||
"top",
|
"top",
|
||||||
"location",
|
"location",
|
||||||
"document",
|
"document",
|
||||||
|
"eval",
|
||||||
];
|
];
|
||||||
|
|
||||||
pub fn rewrite(
|
pub fn rewrite(js: &str, url: Url, config: Config) -> Vec<u8> {
|
||||||
js: &str,
|
|
||||||
url: Url,
|
|
||||||
prefix: String,
|
|
||||||
encode: EncodeFn,
|
|
||||||
wrapfn: String,
|
|
||||||
importfn: String,
|
|
||||||
) -> Vec<u8> {
|
|
||||||
let allocator = Allocator::default();
|
let allocator = Allocator::default();
|
||||||
let source_type = SourceType::default();
|
let source_type = SourceType::default();
|
||||||
let ret = Parser::new(&allocator, js, source_type).parse();
|
let ret = Parser::new(&allocator, js, source_type).parse();
|
||||||
|
@ -274,10 +299,7 @@ pub fn rewrite(
|
||||||
let mut ast_pass = Rewriter {
|
let mut ast_pass = Rewriter {
|
||||||
jschanges: Vec::new(),
|
jschanges: Vec::new(),
|
||||||
base: url,
|
base: url,
|
||||||
prefix,
|
config,
|
||||||
encode,
|
|
||||||
wrapfn,
|
|
||||||
importfn,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ast_pass.visit_program(&program);
|
ast_pass.visit_program(&program);
|
||||||
|
|
|
@ -8,10 +8,6 @@ export const issw = "ServiceWorkerGlobalScope" in self;
|
||||||
export const isdedicated = "DedicatedWorkerGlobalScope" in self;
|
export const isdedicated = "DedicatedWorkerGlobalScope" in self;
|
||||||
export const isshared = "SharedWorkerGlobalScope" in self;
|
export const isshared = "SharedWorkerGlobalScope" in self;
|
||||||
|
|
||||||
export const wrapfn = "$scramjet$wrap";
|
|
||||||
export const trysetfn = "$scramjet$tryset";
|
|
||||||
export const importfn = "$scramjet$import";
|
|
||||||
|
|
||||||
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.SCRAMJET in self)) {
|
||||||
|
|
|
@ -10,3 +10,5 @@ export const {
|
||||||
rewriteWorkers,
|
rewriteWorkers,
|
||||||
},
|
},
|
||||||
} = self.$scramjet.shared;
|
} = self.$scramjet.shared;
|
||||||
|
|
||||||
|
export const config = self.$scramjet.config;
|
||||||
|
|
|
@ -1,24 +1,47 @@
|
||||||
import { ScramjetClient, ProxyCtx } from "../client";
|
import { ScramjetClient, ProxyCtx } from "../client";
|
||||||
import { rewriteJs } from "../shared";
|
import { config, rewriteJs } from "../shared";
|
||||||
|
|
||||||
function rewriteFunction(ctx: ProxyCtx) {
|
function rewriteFunction(ctx: ProxyCtx) {
|
||||||
for (const i in ctx.args) {
|
for (const i in ctx.args) {
|
||||||
ctx.args[i] = rewriteJs(ctx.args[i]);
|
ctx.args[i] = rewriteJs(ctx.args[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.return(ctx.fn(...ctx.args));
|
ctx.return(ctx.fn(...ctx.args));
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function (client: ScramjetClient, self: Self) {
|
export default function (client: ScramjetClient, self: Self) {
|
||||||
client.Proxy("Function", {
|
client.Proxy("Function", {
|
||||||
apply(ctx) {
|
apply(ctx) {
|
||||||
rewriteFunction(ctx);
|
rewriteFunction(ctx);
|
||||||
},
|
},
|
||||||
|
|
||||||
construct(ctx) {
|
construct(ctx) {
|
||||||
rewriteFunction(ctx);
|
rewriteFunction(ctx);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Function.prototype.constructor = Function;
|
Function.prototype.constructor = Function;
|
||||||
|
|
||||||
|
// used for proxying *direct eval*
|
||||||
|
// eval("...") -> eval($scramjet$rewrite("..."))
|
||||||
|
Object.defineProperty(self, config.rewritefn, {
|
||||||
|
value: function (js: any) {
|
||||||
|
if (typeof js !== "string") return js;
|
||||||
|
|
||||||
|
const rewritten = rewriteJs(js, client.url);
|
||||||
|
|
||||||
|
return rewritten;
|
||||||
|
},
|
||||||
|
writable: false,
|
||||||
|
configurable: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function indirectEval(this: ScramjetClient, js: any) {
|
||||||
|
// > If the argument of eval() is not a string, eval() returns the argument unchanged
|
||||||
|
if (typeof js !== "string") return js;
|
||||||
|
|
||||||
|
const indirection = this.global.eval;
|
||||||
|
|
||||||
|
return indirection(rewriteJs(js, this.url) as string);
|
||||||
}
|
}
|
|
@ -1,8 +1,7 @@
|
||||||
import { encodeUrl } from "../shared";
|
import { config, encodeUrl } from "../shared";
|
||||||
import { importfn } from "../";
|
|
||||||
|
|
||||||
export default function (client, self) {
|
export default function (client, self) {
|
||||||
self[importfn] = function (base) {
|
self[config.importfn] = function (base) {
|
||||||
return function (url) {
|
return function (url) {
|
||||||
const resolved = new URL(url, base).href;
|
const resolved = new URL(url, base).href;
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import { iswindow, isworker, trysetfn, wrapfn } from "..";
|
import { iswindow, isworker } from "..";
|
||||||
import { ScramjetClient } from "../client";
|
import { ScramjetClient } from "../client";
|
||||||
|
import { config } from "../shared";
|
||||||
|
|
||||||
export default function (client: ScramjetClient, self: typeof globalThis) {
|
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, {
|
Object.defineProperty(self, config.wrapfn, {
|
||||||
value: function (identifier: any, args: any) {
|
value: function (identifier: any, args: any) {
|
||||||
if (args && typeof args === "object" && args.length === 0)
|
if (args && typeof args === "object" && args.length === 0)
|
||||||
for (const arg of args) {
|
for (const arg of args) {
|
||||||
|
@ -58,7 +59,7 @@ export default function (client: ScramjetClient, self: typeof globalThis) {
|
||||||
// ((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
|
||||||
Object.defineProperty(self, trysetfn, {
|
Object.defineProperty(self, config.trysetfn, {
|
||||||
value: function (lhs: any, op: string, rhs: any) {
|
value: function (lhs: any, op: string, rhs: any) {
|
||||||
if (lhs instanceof Location) {
|
if (lhs instanceof Location) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { encodeUrl } from "../shared/rewriters/url";
|
import { encodeUrl } from "../shared/rewriters/url";
|
||||||
import { ScramjetClient } from "./client";
|
import { ScramjetClient } from "./client";
|
||||||
import { wrapfn } from ".";
|
import { indirectEval } from "./shared/eval";
|
||||||
|
import { config } from "./shared";
|
||||||
|
|
||||||
export function createWindowProxy(
|
export function createWindowProxy(
|
||||||
client: ScramjetClient,
|
client: ScramjetClient,
|
||||||
|
@ -9,16 +10,17 @@ export function createWindowProxy(
|
||||||
return new Proxy(self, {
|
return new Proxy(self, {
|
||||||
get(target, prop) {
|
get(target, prop) {
|
||||||
const propIsString = typeof prop === "string";
|
const propIsString = typeof prop === "string";
|
||||||
if (propIsString && prop === "location") {
|
if (prop === "location") return client.locationProxy;
|
||||||
return client.locationProxy;
|
|
||||||
} else if (
|
if (
|
||||||
propIsString &&
|
propIsString &&
|
||||||
["window", "top", "self", "globalThis", "parent"].includes(prop)
|
["window", "top", "self", "globalThis", "parent"].includes(prop)
|
||||||
) {
|
)
|
||||||
return self[wrapfn](self[prop]);
|
return self[config.wrapfn](self[prop]);
|
||||||
} else if (propIsString && prop === "$scramjet") {
|
|
||||||
return;
|
if (prop === "$scramjet") return;
|
||||||
}
|
|
||||||
|
if (prop === "eval") return indirectEval.bind(client);
|
||||||
|
|
||||||
const value = Reflect.get(target, prop);
|
const value = Reflect.get(target, prop);
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,10 @@ if (!self.$scramjet) {
|
||||||
self.$scramjet.config = {
|
self.$scramjet.config = {
|
||||||
prefix: "/scramjet/",
|
prefix: "/scramjet/",
|
||||||
codec: self.$scramjet.codecs.plain,
|
codec: self.$scramjet.codecs.plain,
|
||||||
|
wrapfn: "$scramjet$wrap",
|
||||||
|
trysetfn: "$scramjet$tryset",
|
||||||
|
importfn: "$scramjet$import",
|
||||||
|
rewritefn: "$scramjet$rewrite",
|
||||||
config: "/scram/scramjet.config.js",
|
config: "/scram/scramjet.config.js",
|
||||||
shared: "/scram/scramjet.shared.js",
|
shared: "/scram/scramjet.shared.js",
|
||||||
worker: "/scram/scramjet.worker.js",
|
worker: "/scram/scramjet.worker.js",
|
||||||
|
|
|
@ -24,25 +24,21 @@ export function rewriteJs(js: string | ArrayBuffer, origin?: URL) {
|
||||||
if ("window" in globalThis) origin ??= new URL(decodeUrl(location.href));
|
if ("window" in globalThis) origin ??= new URL(decodeUrl(location.href));
|
||||||
|
|
||||||
const before = performance.now();
|
const before = performance.now();
|
||||||
|
const cfg = {
|
||||||
|
prefix: self.$scramjet.config.prefix,
|
||||||
|
codec: self.$scramjet.config.codec.encode,
|
||||||
|
wrapfn: self.$scramjet.config.wrapfn,
|
||||||
|
trysetfn: self.$scramjet.config.trysetfn,
|
||||||
|
importfn: self.$scramjet.config.importfn,
|
||||||
|
rewritefn: self.$scramjet.config.rewritefn,
|
||||||
|
};
|
||||||
if (typeof js === "string") {
|
if (typeof js === "string") {
|
||||||
js = new TextDecoder().decode(
|
js = new TextDecoder().decode(rewrite_js(js, origin.toString(), cfg));
|
||||||
rewrite_js(
|
|
||||||
js,
|
|
||||||
origin.toString(),
|
|
||||||
self.$scramjet.config.prefix,
|
|
||||||
self.$scramjet.config.codec.encode as any,
|
|
||||||
"$scramjet$wrap",
|
|
||||||
"$scramjet$import"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
js = rewrite_js_from_arraybuffer(
|
js = rewrite_js_from_arraybuffer(
|
||||||
new Uint8Array(js),
|
new Uint8Array(js),
|
||||||
origin.toString(),
|
origin.toString(),
|
||||||
self.$scramjet.config.prefix,
|
cfg
|
||||||
self.$scramjet.config.codec.encode as any,
|
|
||||||
"$scramjet$wrap",
|
|
||||||
"$scramjet$import"
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const after = performance.now();
|
const after = performance.now();
|
||||||
|
|
4
src/types.d.ts
vendored
4
src/types.d.ts
vendored
|
@ -34,6 +34,10 @@ declare global {
|
||||||
config: {
|
config: {
|
||||||
prefix: string;
|
prefix: string;
|
||||||
codec: Codec;
|
codec: Codec;
|
||||||
|
wrapfn: string;
|
||||||
|
trysetfn: string;
|
||||||
|
importfn: string;
|
||||||
|
rewritefn: string;
|
||||||
config: string;
|
config: string;
|
||||||
shared: string;
|
shared: string;
|
||||||
worker: string;
|
worker: string;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue