rewrite the rewriter

This commit is contained in:
velzie 2024-07-18 20:26:13 -04:00
parent 73c1c8a5c8
commit 6a5ecc4efc
No known key found for this signature in database
GPG key ID: 048413F95F0DDE1F
6 changed files with 62 additions and 128 deletions

11
rewriter/Cargo.lock generated
View file

@ -67,6 +67,16 @@ dependencies = [
"static_assertions", "static_assertions",
] ]
[[package]]
name = "console_error_panic_hook"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
dependencies = [
"cfg-if",
"wasm-bindgen",
]
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.8.20" version = "0.8.20"
@ -449,6 +459,7 @@ dependencies = [
name = "rewriter" name = "rewriter"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"console_error_panic_hook",
"js-sys", "js-sys",
"oxc_allocator", "oxc_allocator",
"oxc_ast", "oxc_ast",

View file

@ -7,6 +7,7 @@ edition = "2021"
crate-type = ["cdylib"] crate-type = ["cdylib"]
[dependencies] [dependencies]
console_error_panic_hook = "0.1.7"
js-sys = "0.3.69" js-sys = "0.3.69"
oxc_allocator = "0.20.0" oxc_allocator = "0.20.0"
oxc_ast = { version = "0.20.0", features = ["serialize"]} oxc_ast = { version = "0.20.0", features = ["serialize"]}

View file

@ -1,5 +1,6 @@
RUSTFLAGS='-C target-feature=+atomics,+bulk-memory,+simd128' cargo build --lib --target wasm32-unknown-unknown -Z build-std=panic_abort,std --release RUSTFLAGS='-C target-feature=+atomics,+bulk-memory,+simd128' cargo build --lib --target wasm32-unknown-unknown -Z build-std=panic_abort,std --release
wasm-bindgen --weak-refs --target web --out-dir out/ target/wasm32-unknown-unknown/release/rewriter.wasm wasm-bindgen --weak-refs --target web --out-dir out/ target/wasm32-unknown-unknown/release/rewriter.wasm
# wasm-bindgen --keep-debug --weak-refs --target web --out-dir out/ target/wasm32-unknown-unknown/release/rewriter.wasm
sed -i 's/import.meta.url/""/g' out/rewriter.js sed -i 's/import.meta.url/""/g' out/rewriter.js
@ -8,6 +9,7 @@ cd ..
WASM=rewriter/out/rewriter_bg.wasm 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 -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 echo -n "self.WASM = '" > static/wasm.js
base64 -w0 < "rewriter/out/optimized.wasm" >> static/wasm.js base64 -w0 < "rewriter/out/optimized.wasm" >> static/wasm.js

View file

@ -1,6 +1,9 @@
pub mod rewrite; pub mod rewrite;
use std::str::{from_utf8, FromStr}; use std::{
panic,
str::{from_utf8, FromStr},
};
use js_sys::Uint8Array; use js_sys::Uint8Array;
use rewrite::rewrite; use rewrite::rewrite;
@ -13,6 +16,11 @@ extern "C" {
fn log(s: &str); fn log(s: &str);
} }
#[wasm_bindgen]
pub fn init() {
panic::set_hook(Box::new(console_error_panic_hook::hook));
}
#[wasm_bindgen] #[wasm_bindgen]
pub fn rewrite_js(js: &str, url: &str) -> Vec<u8> { pub fn rewrite_js(js: &str, url: &str) -> Vec<u8> {
rewrite(js, Url::from_str(url).unwrap()) rewrite(js, Url::from_str(url).unwrap())

View file

@ -2,7 +2,7 @@ use oxc_allocator::Allocator;
use oxc_ast::{ use oxc_ast::{
ast::{ ast::{
AssignmentTarget, Class, Expression, Function, IdentifierReference, MemberExpression, AssignmentTarget, Class, Expression, Function, IdentifierReference, MemberExpression,
TSImportType, ObjectExpression, ObjectProperty, ObjectPropertyKind, TSImportType,
}, },
visit::walk, visit::walk,
Visit, Visit,
@ -37,47 +37,21 @@ struct Rewriter {
} }
impl<'a> Visit<'a> for Rewriter { impl<'a> Visit<'a> for Rewriter {
fn visit_assignment_expression(&mut self, expr: &oxc_ast::ast::AssignmentExpression<'a>) { fn visit_identifier_reference(&mut self, it: &IdentifierReference<'a>) {
// if expr.left.is_simple_assignment_target() { if UNSAFE_GLOBALS.contains(&it.name.to_string().as_str()) {
// let name = expr self.jschanges.push(JsChange::GenericChange {
// .left span: it.span,
// .as_simple_assignment_target() text: format!("(globalThis.$s({}))", it.name),
// .unwrap() });
// .get_identifier()
// .unwrap();
// if name == "location" {
// use oxc_ast::ast::Expression as E;
// let span = match &expr.right {
// E::Super(s) => s.span,
// E::ThisExpression(s) => s.span,
// E::Identifier(s) => s.span,
// E::NumericLiteral(s) => s.span,
// E::AssignmentExpression(s) => s.span,
//
// _ => todo!("{:?}", expr.right),
// };
// self.jschanges.push(JsChange::Assignment {
// name: name.to_string(),
// entirespan: expr.span,
// rhsspan: span,
// });
// }
// }
match &expr.right {
Expression::Identifier(s) => {
if UNSAFE_GLOBALS.contains(&s.name.to_string().as_str()) {
self.jschanges.push(JsChange::GenericChange {
span: s.span,
text: format!("(globalThis.$s({}))", s.name),
});
}
}
_ => {
walk::walk_assignment_expression(self, expr);
}
} }
} }
fn visit_this_expression(&mut self, it: &oxc_ast::ast::ThisExpression) {
self.jschanges.push(JsChange::GenericChange {
span: it.span,
text: "(globalThis.$s(this))".to_string(),
});
}
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 url = self.base.join(&name).unwrap(); let url = self.base.join(&name).unwrap();
@ -97,24 +71,29 @@ impl<'a> Visit<'a> for Rewriter {
}); });
walk::walk_import_expression(self, it); walk::walk_import_expression(self, it);
} }
fn visit_variable_declarator(&mut self, it: &oxc_ast::ast::VariableDeclarator<'a>) {
match &it.init { fn visit_object_expression(&mut self, it: &oxc_ast::ast::ObjectExpression<'a>) {
Some(Expression::Identifier(s)) => { for prop in &it.properties {
if UNSAFE_GLOBALS.contains(&s.name.to_string().as_str()) { match prop {
self.jschanges.push(JsChange::GenericChange { ObjectPropertyKind::ObjectProperty(p) => match &p.value {
span: s.span, Expression::Identifier(s) => {
text: format!("(globalThis.$s({}))", s.name), if UNSAFE_GLOBALS.contains(&s.name.to_string().as_str()) {
}); if p.shorthand {
} self.jschanges.push(JsChange::GenericChange {
} span: s.span,
_ => { text: format!("{}: (globalThis.$s({}))", s.name, s.name),
walk::walk_variable_declarator(self, it); });
return;
}
}
}
_ => {}
},
_ => {}
} }
} }
}
fn visit_member_expression(&mut self, it: &MemberExpression<'a>) { walk::walk_object_expression(self, it);
self.trace_member(it);
} }
} }
@ -130,60 +109,6 @@ const UNSAFE_GLOBALS: [&str; 8] = [
"document", "document",
]; ];
impl Rewriter {
fn trace_member<'a>(&mut self, it: &MemberExpression<'a>) {
match &it {
MemberExpression::StaticMemberExpression(s) => match &s.object {
Expression::Identifier(obj) => {
if UNSAFE_GLOBALS.contains(&obj.name.to_string().as_str()) {
self.jschanges.push(JsChange::GenericChange {
span: obj.span,
text: format!("(globalThis.$s({}))", obj.name),
});
}
}
Expression::ThisExpression(obj) => {
self.jschanges.push(JsChange::GenericChange {
span: obj.span,
text: "(globalThis.$s(this))".to_string(),
});
}
_ => {
if it.object().is_member_expression() {
self.trace_member(it.object().as_member_expression().unwrap());
} else {
walk::walk_member_expression(self, it);
}
}
},
MemberExpression::ComputedMemberExpression(s) => match &s.object {
Expression::Identifier(obj) => {
if UNSAFE_GLOBALS.contains(&obj.name.to_string().as_str()) {
self.jschanges.push(JsChange::GenericChange {
span: obj.span,
text: format!("(globalThis.$s({}))", obj.name),
});
}
}
Expression::ThisExpression(obj) => {
self.jschanges.push(JsChange::GenericChange {
span: obj.span,
text: "(globalThis.$s(this))".to_string(),
});
}
_ => {
if it.object().is_member_expression() {
self.trace_member(it.object().as_member_expression().unwrap());
} else {
walk::walk_member_expression(self, it);
}
}
},
_ => {}
}
}
}
pub fn rewrite(js: &str, url: Url) -> Vec<u8> { pub fn rewrite(js: &str, url: Url) -> Vec<u8> {
let allocator = Allocator::default(); let allocator = Allocator::default();
let source_type = SourceType::default(); let source_type = SourceType::default();
@ -259,24 +184,6 @@ pub fn rewrite(js: &str, url: Url) -> Vec<u8> {
// offset = (offset as i64 + (text.len() as i64 - len as i64)) as usize; // offset = (offset as i64 + (text.len() as i64 - len as i64)) as usize;
} }
// JsChange::Assignment {
// name,
// entirespan,
// rhsspan,
// } => {
// let len = (entirespan.end - entirespan.start) as usize;
// let start = entirespan.start as usize + offset;
// let end = entirespan.end as usize + offset;
//
// let text = format!(
// "$set({}, {})",
// name,
// &js[rhsspan.start as usize..rhsspan.end as usize]
// );
// rewritten.replace_range(start..end, &text);
//
// offset += text.len() - len;
// }
_ => {} _ => {}
} }
} }

View file

@ -2,6 +2,7 @@ import { decodeUrl } from "./url";
// i am a cat. i like to be petted. i like to be fed. i like to be // i am a cat. i like to be petted. i like to be fed. i like to be
import { import {
init,
initSync, initSync,
rewrite_js, rewrite_js,
rewrite_js_from_arraybuffer, rewrite_js_from_arraybuffer,
@ -14,6 +15,10 @@ initSync(
) )
); );
init();
Error.stackTraceLimit = 50
global.rws = rewriteJs; global.rws = rewriteJs;
export function rewriteJs(js: string | ArrayBuffer, origin?: URL) { 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));