diff --git a/rewriter/Cargo.lock b/rewriter/Cargo.lock index 9fc5628..c852b67 100644 --- a/rewriter/Cargo.lock +++ b/rewriter/Cargo.lock @@ -67,6 +67,16 @@ dependencies = [ "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]] name = "crossbeam-utils" version = "0.8.20" @@ -449,6 +459,7 @@ dependencies = [ name = "rewriter" version = "0.1.0" dependencies = [ + "console_error_panic_hook", "js-sys", "oxc_allocator", "oxc_ast", diff --git a/rewriter/Cargo.toml b/rewriter/Cargo.toml index 9099f1e..9d3364a 100644 --- a/rewriter/Cargo.toml +++ b/rewriter/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] +console_error_panic_hook = "0.1.7" js-sys = "0.3.69" oxc_allocator = "0.20.0" oxc_ast = { version = "0.20.0", features = ["serialize"]} diff --git a/rewriter/build.sh b/rewriter/build.sh index 553a286..58c1620 100644 --- a/rewriter/build.sh +++ b/rewriter/build.sh @@ -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 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 @@ -8,6 +9,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 +# cp "$WASM" rewriter/out/optimized.wasm echo -n "self.WASM = '" > static/wasm.js base64 -w0 < "rewriter/out/optimized.wasm" >> static/wasm.js diff --git a/rewriter/src/lib.rs b/rewriter/src/lib.rs index 55fd661..3b2545e 100644 --- a/rewriter/src/lib.rs +++ b/rewriter/src/lib.rs @@ -1,6 +1,9 @@ pub mod rewrite; -use std::str::{from_utf8, FromStr}; +use std::{ + panic, + str::{from_utf8, FromStr}, +}; use js_sys::Uint8Array; use rewrite::rewrite; @@ -13,6 +16,11 @@ extern "C" { fn log(s: &str); } +#[wasm_bindgen] +pub fn init() { + panic::set_hook(Box::new(console_error_panic_hook::hook)); +} + #[wasm_bindgen] pub fn rewrite_js(js: &str, url: &str) -> Vec { rewrite(js, Url::from_str(url).unwrap()) diff --git a/rewriter/src/rewrite.rs b/rewriter/src/rewrite.rs index 531731c..951e0f9 100644 --- a/rewriter/src/rewrite.rs +++ b/rewriter/src/rewrite.rs @@ -2,7 +2,7 @@ use oxc_allocator::Allocator; use oxc_ast::{ ast::{ AssignmentTarget, Class, Expression, Function, IdentifierReference, MemberExpression, - TSImportType, + ObjectExpression, ObjectProperty, ObjectPropertyKind, TSImportType, }, visit::walk, Visit, @@ -37,47 +37,21 @@ struct Rewriter { } impl<'a> Visit<'a> for Rewriter { - fn visit_assignment_expression(&mut self, expr: &oxc_ast::ast::AssignmentExpression<'a>) { - // if expr.left.is_simple_assignment_target() { - // let name = expr - // .left - // .as_simple_assignment_target() - // .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_identifier_reference(&mut self, it: &IdentifierReference<'a>) { + if UNSAFE_GLOBALS.contains(&it.name.to_string().as_str()) { + self.jschanges.push(JsChange::GenericChange { + span: it.span, + text: format!("(globalThis.$s({}))", it.name), + }); } } + 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>) { let name = it.source.value.to_string(); let url = self.base.join(&name).unwrap(); @@ -97,24 +71,29 @@ impl<'a> Visit<'a> for Rewriter { }); walk::walk_import_expression(self, it); } - fn visit_variable_declarator(&mut self, it: &oxc_ast::ast::VariableDeclarator<'a>) { - match &it.init { - Some(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_variable_declarator(self, it); + + fn visit_object_expression(&mut self, it: &oxc_ast::ast::ObjectExpression<'a>) { + for prop in &it.properties { + match prop { + ObjectPropertyKind::ObjectProperty(p) => match &p.value { + Expression::Identifier(s) => { + 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), + }); + return; + } + } + } + _ => {} + }, + _ => {} } } - } - fn visit_member_expression(&mut self, it: &MemberExpression<'a>) { - self.trace_member(it); + walk::walk_object_expression(self, it); } } @@ -130,60 +109,6 @@ const UNSAFE_GLOBALS: [&str; 8] = [ "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 { let allocator = Allocator::default(); let source_type = SourceType::default(); @@ -259,24 +184,6 @@ pub fn rewrite(js: &str, url: Url) -> Vec { // 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; - // } _ => {} } } diff --git a/src/shared/rewriters/js.ts b/src/shared/rewriters/js.ts index 8e6b868..a5c99ef 100644 --- a/src/shared/rewriters/js.ts +++ b/src/shared/rewriters/js.ts @@ -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 import { + init, initSync, rewrite_js, rewrite_js_from_arraybuffer, @@ -14,6 +15,10 @@ initSync( ) ); +init(); + +Error.stackTraceLimit = 50 + global.rws = rewriteJs; export function rewriteJs(js: string | ArrayBuffer, origin?: URL) { if ("window" in globalThis) origin ??= new URL(decodeUrl(location.href));