mirror of
https://github.com/MercuryWorkshop/scramjet.git
synced 2025-05-15 07:20:02 -04:00
rewriter error handling
This commit is contained in:
parent
d2f1e10a6c
commit
6fc473068f
4 changed files with 99 additions and 55 deletions
1
rewriter/Cargo.lock
generated
1
rewriter/Cargo.lock
generated
|
@ -999,6 +999,7 @@ dependencies = [
|
|||
"rand",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"thiserror",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
|
|
|
@ -35,6 +35,7 @@ oxc_syntax = "0.20.0"
|
|||
rand = "0.8.5"
|
||||
serde = "1.0.204"
|
||||
serde-wasm-bindgen = "0.6.5"
|
||||
thiserror = "1.0.64"
|
||||
url = "2.5.2"
|
||||
wasm-bindgen = "0.2.92"
|
||||
web-sys = { version = "0.3.72", features = ["Url"] }
|
||||
|
|
|
@ -4,13 +4,55 @@ use std::{panic, str::FromStr};
|
|||
|
||||
use js_sys::{Function, Object, Reflect};
|
||||
use rewrite::{rewrite, Config, EncodeFn};
|
||||
use thiserror::Error;
|
||||
use url::Url;
|
||||
use wasm_bindgen::{prelude::*, throw_str};
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum RewriterError {
|
||||
#[error("JS: {0}")]
|
||||
Js(String),
|
||||
#[error("URL parse error: {0}")]
|
||||
Url(#[from] url::ParseError),
|
||||
|
||||
#[error("{0} was not {1}")]
|
||||
Not(String, &'static str),
|
||||
#[error("❗❗❗ ❗❗❗ REWRITER OFFSET OOB FAIL ❗❗❗ ❗❗❗")]
|
||||
Oob,
|
||||
}
|
||||
|
||||
impl From<JsValue> for RewriterError {
|
||||
fn from(value: JsValue) -> Self {
|
||||
Self::Js(format!("{:?}", value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RewriterError> for JsValue {
|
||||
fn from(value: RewriterError) -> Self {
|
||||
JsError::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl RewriterError {
|
||||
fn not_str(x: &str, obj: &JsValue) -> Self {
|
||||
Self::Not(format!("{:?} in {:?}", x, obj), "string")
|
||||
}
|
||||
|
||||
fn not_fn(obj: JsValue) -> Self {
|
||||
Self::Not(format!("{:?}", obj), "function")
|
||||
}
|
||||
|
||||
fn not_bool(obj: &JsValue) -> Self {
|
||||
Self::Not(format!("{:?}", obj), "bool")
|
||||
}
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, RewriterError>;
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_namespace = console)]
|
||||
fn log(s: &str);
|
||||
fn error(s: &str);
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
|
@ -18,64 +60,62 @@ pub fn init() {
|
|||
panic::set_hook(Box::new(console_error_panic_hook::hook));
|
||||
}
|
||||
|
||||
fn create_encode_function(encode: JsValue) -> EncodeFn {
|
||||
let Ok(encode) = encode.dyn_into::<Function>() else {
|
||||
throw_str("invalid encode function");
|
||||
};
|
||||
fn create_encode_function(encode: JsValue) -> Result<EncodeFn> {
|
||||
let encode = encode.dyn_into::<Function>()?;
|
||||
|
||||
Box::new(move |str| {
|
||||
Ok(Box::new(move |str| {
|
||||
encode
|
||||
.call1(&JsValue::NULL, &str.into())
|
||||
.unwrap()
|
||||
.as_string()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn get_obj(obj: &JsValue, k: &str) -> JsValue {
|
||||
Reflect::get(obj, &k.into()).unwrap()
|
||||
fn get_obj(obj: &JsValue, k: &str) -> Result<JsValue> {
|
||||
Ok(Reflect::get(obj, &k.into())?)
|
||||
}
|
||||
|
||||
fn get_str(obj: &JsValue, k: &str) -> String {
|
||||
Reflect::get(obj, &k.into()).unwrap().as_string().unwrap()
|
||||
fn get_str(obj: &JsValue, k: &str) -> Result<String> {
|
||||
Reflect::get(obj, &k.into())?
|
||||
.as_string()
|
||||
.ok_or_else(|| RewriterError::not_str(k, obj))
|
||||
}
|
||||
|
||||
fn get_flag(scramjet: &Object, url: &str, flag: &str) -> bool {
|
||||
let fenabled = get_obj(scramjet, "flagEnabled")
|
||||
fn get_flag(scramjet: &Object, url: &str, flag: &str) -> Result<bool> {
|
||||
let fenabled = get_obj(scramjet, "flagEnabled")?
|
||||
.dyn_into::<Function>()
|
||||
.unwrap();
|
||||
fenabled
|
||||
.call2(
|
||||
&JsValue::NULL,
|
||||
&flag.into(),
|
||||
&web_sys::Url::new(url).expect("invalid url").into(),
|
||||
)
|
||||
.expect("error in flagEnabled")
|
||||
.as_bool()
|
||||
.expect("not bool returned from flagEnabled")
|
||||
.map_err(RewriterError::not_fn)?;
|
||||
let ret = fenabled.call2(
|
||||
&JsValue::NULL,
|
||||
&flag.into(),
|
||||
&web_sys::Url::new(url).expect("invalid url").into(),
|
||||
)?;
|
||||
|
||||
ret.as_bool().ok_or_else(|| RewriterError::not_bool(&ret))
|
||||
}
|
||||
|
||||
fn get_config(scramjet: &Object, url: &str) -> Config {
|
||||
let codec = &get_obj(scramjet, "codec");
|
||||
let config = &get_obj(scramjet, "config");
|
||||
let globals = &get_obj(config, "globals");
|
||||
fn get_config(scramjet: &Object, url: &str) -> Result<Config> {
|
||||
let codec = &get_obj(scramjet, "codec")?;
|
||||
let config = &get_obj(scramjet, "config")?;
|
||||
let globals = &get_obj(config, "globals")?;
|
||||
|
||||
Config {
|
||||
prefix: get_str(config, "prefix"),
|
||||
encode: create_encode_function(get_obj(codec, "encode")),
|
||||
Ok(Config {
|
||||
prefix: get_str(config, "prefix")?,
|
||||
encode: create_encode_function(get_obj(codec, "encode")?)?,
|
||||
|
||||
wrapfn: get_str(globals, "wrapfn"),
|
||||
importfn: get_str(globals, "importfn"),
|
||||
rewritefn: get_str(globals, "rewritefn"),
|
||||
metafn: get_str(globals, "metafn"),
|
||||
setrealmfn: get_str(globals, "setrealmfn"),
|
||||
pushsourcemapfn: get_str(globals, "pushsourcemapfn"),
|
||||
wrapfn: get_str(globals, "wrapfn")?,
|
||||
importfn: get_str(globals, "importfn")?,
|
||||
rewritefn: get_str(globals, "rewritefn")?,
|
||||
metafn: get_str(globals, "metafn")?,
|
||||
setrealmfn: get_str(globals, "setrealmfn")?,
|
||||
pushsourcemapfn: get_str(globals, "pushsourcemapfn")?,
|
||||
|
||||
do_sourcemaps: get_flag(scramjet, url, "sourcemaps"),
|
||||
capture_errors: get_flag(scramjet, url, "captureErrors"),
|
||||
scramitize: get_flag(scramjet, url, "scramitize"),
|
||||
}
|
||||
do_sourcemaps: get_flag(scramjet, url, "sourcemaps")?,
|
||||
capture_errors: get_flag(scramjet, url, "captureErrors")?,
|
||||
scramitize: get_flag(scramjet, url, "scramitize")?,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "drm")]
|
||||
|
@ -89,17 +129,17 @@ fn drmcheck() -> bool {
|
|||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn rewrite_js(js: &str, url: &str, scramjet: &Object) -> Vec<u8> {
|
||||
pub fn rewrite_js(js: &str, url: &str, scramjet: &Object) -> Result<Vec<u8>> {
|
||||
#[cfg(feature = "drm")]
|
||||
if !drmcheck() {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
rewrite(js, Url::from_str(url).unwrap(), get_config(scramjet, url))
|
||||
rewrite(js, Url::from_str(url)?, get_config(scramjet, url)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn rewrite_js_from_arraybuffer(js: &[u8], url: &str, scramjet: &Object) -> Vec<u8> {
|
||||
pub fn rewrite_js_from_arraybuffer(js: &[u8], url: &str, scramjet: &Object) -> Result<Vec<u8>> {
|
||||
#[cfg(feature = "drm")]
|
||||
if !drmcheck() {
|
||||
return Vec::new();
|
||||
|
@ -108,5 +148,5 @@ pub fn rewrite_js_from_arraybuffer(js: &[u8], url: &str, scramjet: &Object) -> V
|
|||
// 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(), get_config(scramjet, url))
|
||||
rewrite(js, Url::from_str(url)?, get_config(scramjet, url)?)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use core::str;
|
||||
use std::str::from_utf8;
|
||||
|
||||
use crate::{error, Result, RewriterError};
|
||||
use oxc_allocator::Allocator;
|
||||
use oxc_ast::{
|
||||
ast::{
|
||||
|
@ -443,21 +444,20 @@ fn random_string() -> String {
|
|||
.to_string()
|
||||
}
|
||||
|
||||
pub fn rewrite(js: &str, url: Url, config: Config) -> Vec<u8> {
|
||||
pub fn rewrite(js: &str, url: Url, config: Config) -> Result<Vec<u8>> {
|
||||
let allocator = Allocator::default();
|
||||
let source_type = SourceType::default();
|
||||
let ret = Parser::new(&allocator, js, source_type).parse();
|
||||
|
||||
for error in ret.errors {
|
||||
for err in ret.errors {
|
||||
let cloned = js.to_string();
|
||||
let error = error.with_source_code(cloned);
|
||||
println!("{error:?}");
|
||||
let err = err.with_source_code(cloned);
|
||||
println!("oxc parse error {err:?}");
|
||||
error(&format!("oxc parse error {err:?}"))
|
||||
}
|
||||
|
||||
let program = ret.program;
|
||||
|
||||
// dbg!(&program);
|
||||
|
||||
let sourcetag = random_string();
|
||||
|
||||
let mut ast_pass = Rewriter {
|
||||
|
@ -540,7 +540,8 @@ pub fn rewrite(js: &str, url: Url, config: Config) -> Vec<u8> {
|
|||
);
|
||||
}
|
||||
|
||||
buffer.extend_from_slice(unsafe { js.get_unchecked(offset..start) }.as_bytes());
|
||||
buffer
|
||||
.extend_from_slice(js.get(offset..start).ok_or(RewriterError::Oob)?.as_bytes());
|
||||
|
||||
buffer.extend_from_slice(text.as_bytes());
|
||||
offset = end;
|
||||
|
@ -570,7 +571,8 @@ pub fn rewrite(js: &str, url: Url, config: Config) -> Vec<u8> {
|
|||
}
|
||||
JsChange::SourceTag { tagstart } => {
|
||||
let start = *tagstart as usize;
|
||||
buffer.extend_from_slice(unsafe { js.get_unchecked(offset..start) }.as_bytes());
|
||||
buffer
|
||||
.extend_from_slice(js.get(offset..start).ok_or(RewriterError::Oob)?.as_bytes());
|
||||
|
||||
let inject = format!("/*scramtag {} {}*/", start, sourcetag);
|
||||
buffer.extend_from_slice(inject.as_bytes());
|
||||
|
@ -589,10 +591,10 @@ pub fn rewrite(js: &str, url: Url, config: Config) -> Vec<u8> {
|
|||
|
||||
sourcemap.extend_from_slice(&buffer);
|
||||
|
||||
return sourcemap;
|
||||
return Ok(sourcemap);
|
||||
}
|
||||
|
||||
buffer
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
fn json_escape_string(s: &str) -> String {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue