/* Copyright Mozilla Foundation * *LicensedundertheApacheLicense,Version2.0,ortheMITlicense, *(the"Licenses")atyouroption.Youmaynotusethisfileexceptin *compliancewithoneoftheLicenses.Youmayobtaincopiesofthe *Licensesat: * *http://www.apache.org/licenses/LICENSE-2.0 *http://opensource.org/licenses/MIT * *Unlessrequiredbyapplicablelaworagreedtoinwriting,software *distributedundertheLicensesisdistributedonan"ASIS"BASIS, *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied. *SeetheLicensesforthespecificlanguagegoverningpermissionsand *limitationsundertheLicenses.
*/
use bumpalo; use env_logger; use jsparagus::ast::source_atom_set::SourceAtomSet; use jsparagus::ast::source_slice_list::SourceSliceList; use jsparagus::ast::types::Program; use jsparagus::emitter::{emit, EmitError, EmitOptions}; use jsparagus::parser::{parse_module, parse_script, ParseError, ParseOptions}; use jsparagus::stencil::gcthings::GCThing; use jsparagus::stencil::regexp::RegExpItem; use jsparagus::stencil::result::EmitResult; use jsparagus::stencil::scope::{BindingName, ScopeData}; use jsparagus::stencil::scope_notes::ScopeNote; use jsparagus::stencil::script::{ImmutableScriptData, ScriptStencil, SourceExtent}; use std::boxed::Box; use std::cell::RefCell; use std::collections::HashMap; use std::convert::TryInto; use std::os::raw::{c_char, c_void}; use std::rc::Rc; use std::{mem, slice, str};
/// Convert single Scope data, resolving enclosing index with scope_index_map. fn convert_scope(scope: ScopeData, scope_index_map: &mut HashMap<usize, usize>) -> SmooshScopeData { match scope {
ScopeData::Alias(_) => panic!("alias should be handled in convert_scopes"),
ScopeData::Global(data) => SmooshScopeData::Global(SmooshGlobalScopeData {
bindings: CVec::from(data.base.bindings.into_iter().map(|x| x.into()).collect()),
let_start: data.let_start,
const_start: data.const_start,
}),
ScopeData::Var(data) => { let enclosing: usize = data.enclosing.into();
SmooshScopeData::Var(SmooshVarScopeData {
bindings: CVec::from(data.base.bindings.into_iter().map(|x| x.into()).collect()),
enclosing: *scope_index_map
.get(&enclosing)
.expect("Alias target should be earlier index"),
function_has_extensible_scope: data.function_has_extensible_scope,
first_frame_slot: data.first_frame_slot.into(),
})
}
ScopeData::Lexical(data) => { let enclosing: usize = data.enclosing.into();
SmooshScopeData::Lexical(SmooshLexicalScopeData {
bindings: CVec::from(data.base.bindings.into_iter().map(|x| x.into()).collect()),
const_start: data.const_start,
enclosing: *scope_index_map
.get(&enclosing)
.expect("Alias target should be earlier index"),
first_frame_slot: data.first_frame_slot.into(),
})
}
ScopeData::Function(data) => { let enclosing: usize = data.enclosing.into();
SmooshScopeData::Function(SmooshFunctionScopeData {
bindings: CVec::from(
data.base
.bindings
.into_iter()
.map(|x| COption::from(x.map(|x| x.into())))
.collect(),
),
has_parameter_exprs: data.has_parameter_exprs,
non_positional_formal_start: data.non_positional_formal_start,
var_start: data.var_start,
enclosing: *scope_index_map
.get(&enclosing)
.expect("Alias target should be earlier index"),
first_frame_slot: data.first_frame_slot.into(),
function_index: data.function_index.into(),
is_arrow: data.is_arrow,
})
}
}
}
/// Convert list of Scope data, removing aliases. /// Also create a map between original index into index into result vector /// without aliases. fn convert_scopes(
scopes: Vec<ScopeData>,
scope_index_map: &mut HashMap<usize, usize>,
) -> CVec<SmooshScopeData> { letmut result = Vec::with_capacity(scopes.len()); for (i, scope) in scopes.into_iter().enumerate() { iflet ScopeData::Alias(index) = scope { let mapped_index = *scope_index_map
.get(&index.into())
.expect("Alias target should be earlier index");
scope_index_map.insert(i, mapped_index);
impl From<ScopeNote> for SmooshScopeNote { fn from(note: ScopeNote) -> Self { let start = usize::from(note.start) as u32; let end = usize::from(note.end) as u32; let parent = match note.parent {
Some(index) => usize::from(index) as u32,
None => std::u32::MAX,
}; Self {
index: usize::from(note.index) as u32,
start,
length: end - start,
parent,
}
}
}
#[no_mangle] pubunsafeextern"C"fn smoosh_init() { // Gecko might set a logger before we do, which is all fine; try to // initialize ours, and reset the FilterLevel env_logger::try_init might // have set to what it was in case of initialization failure let filter = log::max_level(); match env_logger::try_init() {
Ok(_) => {}
Err(_) => {
log::set_max_level(filter);
}
}
}
let immutable_script_data = COption::from(script.immutable_script_data.map(|n| n.into()));
let extent = convert_extent(script.extent);
let fun_name = COption::from(script.fun_name.map(|n| n.into())); let fun_nargs = script.fun_nargs; let fun_flags = script.fun_flags.into();
let lazy_function_enclosing_scope_index =
COption::from(script.lazy_function_enclosing_scope_index.map(|index| {
*scope_index_map
.get(&index.into())
.expect("Alias target should be earlier index")
}));
let is_standalone_function = script.is_standalone_function; let was_function_emitted = script.was_function_emitted; let is_singleton_function = script.is_singleton_function;
fn convert_script_data(script_data: ImmutableScriptData) -> SmooshImmutableScriptData { let main_offset = script_data.main_offset; let nfixed = script_data.nfixed.into(); let nslots = script_data.nslots; let body_scope_index = script_data.body_scope_index; let num_ic_entries = script_data.num_ic_entries; let fun_length = script_data.fun_length;
#[no_mangle] pubunsafeextern"C"fn smoosh_run(
text: *const u8,
text_len: usize,
options: &SmooshCompileOptions,
) -> SmooshResult { let text = str::from_utf8(slice::from_raw_parts(text, text_len)).expect("Invalid UTF8"); let allocator = Box::new(bumpalo::Bump::new()); match smoosh(&allocator, text, options) {
Ok(result) => { letmut scope_index_map = HashMap::new();
let scopes = convert_scopes(result.scopes, &mut scope_index_map); let regexps = CVec::from(result.regexps.into_iter().map(|x| x.into()).collect());
let scripts = CVec::from(
result
.scripts
.into_iter()
.map(|x| convert_script(x, &scope_index_map))
.collect(),
);
let script_data_list = CVec::from(
result
.script_data_list
.into_iter()
.map(convert_script_data)
.collect(),
);
let all_atoms_len = result.atoms.len(); let all_atoms = Box::new(result.atoms); let raw_all_atoms = Box::into_raw(all_atoms); let opaque_all_atoms = raw_all_atoms as *mut c_void;
let slices_len = result.slices.len(); let slices = Box::new(result.slices); let raw_slices = Box::into_raw(slices); let opaque_slices = raw_slices as *mut c_void;
let raw_allocator = Box::into_raw(allocator); let opaque_allocator = raw_allocator as *mut c_void;
#[no_mangle] pubunsafeextern"C"fn smoosh_test_parse_script(
text: *const u8,
text_len: usize,
) -> SmooshParseResult { let text = match str::from_utf8(slice::from_raw_parts(text, text_len)) {
Ok(text) => text,
Err(_) => { return SmooshParseResult {
unimplemented: false,
error: CVec::from("Invalid UTF-8\0".to_string().into_bytes()),
};
}
}; let allocator = bumpalo::Bump::new(); let parse_options = ParseOptions::new(); let atoms = Rc::new(RefCell::new(SourceAtomSet::new())); let slices = Rc::new(RefCell::new(SourceSliceList::new()));
convert_parse_result(parse_script(
&allocator,
text,
&parse_options,
atoms,
slices,
))
}
#[no_mangle] pubunsafeextern"C"fn smoosh_test_parse_module(
text: *const u8,
text_len: usize,
) -> SmooshParseResult { let text = match str::from_utf8(slice::from_raw_parts(text, text_len)) {
Ok(text) => text,
Err(_) => { return SmooshParseResult {
unimplemented: false,
error: CVec::from("Invalid UTF-8\0".to_string().into_bytes()),
};
}
}; let allocator = bumpalo::Bump::new(); let parse_options = ParseOptions::new(); let atoms = Rc::new(RefCell::new(SourceAtomSet::new())); let slices = Rc::new(RefCell::new(SourceSliceList::new()));
convert_parse_result(parse_module(
&allocator,
text,
&parse_options,
atoms,
slices,
))
}
#[no_mangle] pubunsafeextern"C"fn smoosh_free_parse_result(result: SmooshParseResult) { let _ = result.error.into();
}
#[no_mangle] pubunsafeextern"C"fn smoosh_get_atom_at(result: SmooshResult, index: usize) -> *const c_char { let all_atoms = result.all_atoms as *const Vec<&str>; let atom = (*all_atoms)[index];
atom.as_ptr() as *const c_char
}
#[no_mangle] pubunsafeextern"C"fn smoosh_get_atom_len_at(result: SmooshResult, index: usize) -> usize { let all_atoms = result.all_atoms as *const Vec<&str>; let atom = (*all_atoms)[index];
atom.len()
}
#[no_mangle] pubunsafeextern"C"fn smoosh_get_slice_at(result: SmooshResult, index: usize) -> *const c_char { let slices = result.slices as *const Vec<&str>; let slice = (*slices)[index];
slice.as_ptr() as *const c_char
}
#[no_mangle] pubunsafeextern"C"fn smoosh_get_slice_len_at(result: SmooshResult, index: usize) -> usize { let slices = result.slices as *const Vec<&str>; let slice = (*slices)[index];
slice.len()
}
unsafefn free_script(script: SmooshScriptStencil) { let _ = script.gcthings.into();
}
unsafefn free_script_data(script_data: SmooshImmutableScriptData) { let _ = script_data.bytecode.into(); let _ = script_data.scope_notes.into();
}
#[no_mangle] pubunsafeextern"C"fn smoosh_free(result: SmooshResult) { let _ = result.error.into();
let _ = result.scopes.into(); let _ = result.regexps.into();
for fun in result.scripts.into() {
free_script(fun);
}
for script_data in result.script_data_list.into() {
free_script_data(script_data);
}
if !result.all_atoms.is_null() { let _ = Box::from_raw(result.all_atoms as *mut Vec<&str>);
} if !result.slices.is_null() { let _ = Box::from_raw(result.slices as *mut Vec<&str>);
} if !result.allocator.is_null() { let _ = Box::from_raw(result.allocator as *mut bumpalo::Bump);
}
}
fn smoosh<'alloc>(
allocator: &'alloc bumpalo::Bump,
text: &'alloc str,
options: &SmooshCompileOptions,
) -> Result<EmitResult<'alloc>, SmooshError> { let parse_options = ParseOptions::new(); let atoms = Rc::new(RefCell::new(SourceAtomSet::new())); let slices = Rc::new(RefCell::new(SourceSliceList::new())); let text_length = text.len();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.