This commit is contained in:
velzie 2024-07-30 07:22:20 -04:00
commit 2ed32461d9
No known key found for this signature in database
GPG key ID: 048413F95F0DDE1F
10 changed files with 521 additions and 538 deletions

View file

@ -1,4 +1,2 @@
[profile.release]
opt-level = "z"
lto = true
codegen-units = 1
debug = true

View file

@ -7,7 +7,7 @@ cd ..
WASM=rewriter/out/rewriter_bg.wasm
time wasm-opt -O4 --vacuum --dce --enable-threads --enable-bulk-memory --enable-simd "$WASM" -o rewriter/out/optimized.wasm
time wasm-opt -g -O4 --vacuum --dce --enable-threads --enable-bulk-memory --enable-simd "$WASM" -o rewriter/out/optimized.wasm
# cp "$WASM" rewriter/out/optimized.wasm
echo -n "self.WASM = '" > static/wasm.js

2
rewriter/rustfmt.toml Normal file
View file

@ -0,0 +1,2 @@
imports_granularity = "Crate"
hard_tabs = true

View file

@ -5,7 +5,7 @@ use std::{panic, str::FromStr};
use js_sys::{Function, Object, Reflect};
use rewrite::{rewrite, Config, EncodeFn};
use url::Url;
use wasm_bindgen::prelude::*;
use wasm_bindgen::{prelude::*, throw_str};
#[wasm_bindgen]
extern "C" {
@ -18,7 +18,11 @@ pub fn init() {
panic::set_hook(Box::new(console_error_panic_hook::hook));
}
fn create_encode_function(encode: Function) -> EncodeFn {
fn create_encode_function(encode: JsValue) -> EncodeFn {
let Ok(encode) = encode.dyn_into::<Function>() else {
throw_str("invalid encode function");
};
Box::new(move |str| {
encode
.call1(&JsValue::NULL, &str.into())
@ -29,31 +33,30 @@ fn create_encode_function(encode: Function) -> EncodeFn {
})
}
fn get_obj(config: &JsValue, k: &str) -> JsValue {
Reflect::get(config, &k.into()).unwrap()
}
fn get_str(config: &JsValue, k: &str) -> String {
Reflect::get(config, &k.into())
.unwrap()
.as_string()
.unwrap()
}
fn get_config(config: Object) -> Config {
Config {
prefix: get_str(&config, "prefix"),
encode: create_encode_function(get_obj(&get_obj(&config, "codec"), "encode")),
wrapfn: get_str(&config, "wrapfn"),
importfn: get_str(&config, "importfn"),
rewritefn: get_str(&config, "rewritefn"),
}
}
#[wasm_bindgen]
pub fn rewrite_js(js: &str, url: &str, config: Object) -> Vec<u8> {
rewrite(
js,
Url::from_str(url).unwrap(),
Config {
prefix: Reflect::get(&config, &"prefix".into())
.unwrap()
.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(),
},
)
rewrite(js, Url::from_str(url).unwrap(), get_config(config))
}
#[wasm_bindgen]
@ -61,27 +64,5 @@ pub fn rewrite_js_from_arraybuffer(js: &[u8], url: &str, config: Object) -> Vec<
// we know that this is a valid utf-8 string
let js = unsafe { std::str::from_utf8_unchecked(js) };
rewrite(
js,
Url::from_str(url).unwrap(),
Config {
prefix: Reflect::get(&config, &"prefix".into())
.unwrap()
.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(),
},
)
rewrite(js, Url::from_str(url).unwrap(), get_config(config))
}

View file

@ -60,8 +60,12 @@ fn encode_into<E>(
let mut pushed = false;
loop {
// Fast path to skip over safe chars at the beginning of the remaining string
let ascii_len = data.iter()
.take_while(|&&c| matches!(c, b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z' | b'-' | b'.' | b'_' | b'~')).count();
let ascii_len = data
.iter()
.take_while(
|&&c| matches!(c, b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z' | b'-' | b'.' | b'_' | b'~'),
)
.count();
let (safe, rest) = if ascii_len >= data.len() {
if !pushed && may_skip_write {

View file

@ -1,9 +1,6 @@
use oxc_allocator::Allocator;
use oxc_ast::{
ast::{
AssignmentTarget, BindingPattern, BindingPatternKind, Expression, IdentifierReference,
ObjectPropertyKind,
},
ast::{AssignmentTarget, Expression, IdentifierReference, ObjectPropertyKind},
visit::walk,
Visit,
};
@ -208,9 +205,8 @@ impl<'a> Visit<'a> for Rewriter {
walk::walk_statement(self, &it.body);
}
fn visit_update_expression(&mut self, it: &oxc_ast::ast::UpdateExpression<'a>) {
fn visit_update_expression(&mut self, _it: &oxc_ast::ast::UpdateExpression<'a>) {
// then no, don't walk it, we don't care
return;
}
fn visit_assignment_expression(&mut self, it: &oxc_ast::ast::AssignmentExpression<'a>) {
@ -341,7 +337,6 @@ pub fn rewrite(js: &str, url: Url, config: Config) -> Vec<u8> {
op: _,
} => entirespan.start,
JsChange::DebugInject { span } => span.start,
_ => 0,
};
let b = match b {
JsChange::GenericChange { span, text: _ } => span.start,
@ -352,7 +347,6 @@ pub fn rewrite(js: &str, url: Url, config: Config) -> Vec<u8> {
op: _,
} => entirespan.start,
JsChange::DebugInject { span } => span.start,
_ => 0,
};
a.cmp(&b)
});
@ -399,7 +393,7 @@ pub fn rewrite(js: &str, url: Url, config: Config) -> Vec<u8> {
let start = entirespan.start as usize;
buffer.extend_from_slice(js[offset..start].as_bytes());
let opstr = buffer.extend_from_slice(
buffer.extend_from_slice(
format!(
"((t)=>$scramjet$tryset({},\"{}\",t)||{}{}t)({})",
name,
@ -419,7 +413,6 @@ pub fn rewrite(js: &str, url: Url, config: Config) -> Vec<u8> {
offset = span.end as usize;
}
_ => {}
}
}
buffer.extend_from_slice(js[offset..].as_bytes());

View file

@ -192,7 +192,9 @@ export default function (client: ScramjetClient, self: typeof window) {
},
});
}
} catch (e) {}
} catch (e) {
console.log(e);
}
}
}
}

View file

@ -1,11 +1,19 @@
// ts throws an error if you dont do window.fetch
import { ScramjetClient } from "../../client";
import { encodeUrl, rewriteHeaders } from "../../shared";
export default function (client: ScramjetClient, self: typeof globalThis) {
client.Proxy("fetch", {
apply(ctx) {
ctx.args[0] = encodeUrl(ctx.args[0]);
if (typeof ctx.args[0] === "string" || ctx.args[0] instanceof URL) {
ctx.args[0].toString();
ctx.args[0] = encodeUrl(ctx.args[0].toString());
} else if (ctx.args[0] instanceof Request && ctx.args[0].url) {
Object.defineProperty(ctx.args[0], "url", {
value: encodeUrl(ctx.args[0].url),
});
}
},
});

View file

@ -37,7 +37,7 @@ function traverseParsedHtml(node, origin?: URL) {
}
/* url attributes */
for (const urlAttr of ["src", "href", "action", "formaction"]) {
for (const urlAttr of ["src", "href", "action", "formaction", "poster"]) {
if (
hasAttrib(node, urlAttr) &&
!isScramjetFile(node.attribs[urlAttr]) &&
@ -52,6 +52,7 @@ function traverseParsedHtml(node, origin?: URL) {
"form",
"media",
"source",
"video",
].includes(node.name)
) {
const value = node.attribs[urlAttr];

View file

@ -24,21 +24,15 @@ export function rewriteJs(js: string | ArrayBuffer, origin?: URL) {
if ("window" in globalThis) origin ??= new URL(decodeUrl(location.href));
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") {
js = new TextDecoder().decode(rewrite_js(js, origin.toString(), cfg));
js = new TextDecoder().decode(
rewrite_js(js, origin.toString(), self.$scramjet.config)
);
} else {
js = rewrite_js_from_arraybuffer(
new Uint8Array(js),
origin.toString(),
cfg
self.$scramjet.config
);
}
const after = performance.now();