Skip to content

Commit 16e7d61

Browse files
committed
Implement basic deaserializer
1 parent db0c916 commit 16e7d61

File tree

5 files changed

+279
-48
lines changed

5 files changed

+279
-48
lines changed

boa_cli/src/debug/snapshot.rs

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,59 @@
1-
use std::{fs::OpenOptions, io::Write};
1+
use std::{
2+
fs::{File, OpenOptions},
3+
io::{Read, Write},
4+
};
25

36
use boa_engine::{
4-
object::ObjectInitializer, snapshot::SnapshotSerializer, Context, JsNativeError, JsObject,
5-
JsResult, JsValue, NativeFunction,
7+
object::ObjectInitializer,
8+
snapshot::{Snapshot, SnapshotSerializer},
9+
Context, JsNativeError, JsObject, JsResult, JsValue, NativeFunction,
610
};
711

812
const SNAPSHOT_PATH: &str = "./snapshot.bin";
913

14+
fn get_file_as_byte_vec(filename: &str) -> Vec<u8> {
15+
let mut f = File::open(&filename).expect("no file found");
16+
let metadata = std::fs::metadata(&filename).expect("unable to read metadata");
17+
let mut buffer = vec![0; metadata.len() as usize];
18+
f.read(&mut buffer).expect("buffer overflow");
19+
20+
buffer
21+
}
22+
1023
fn create(_: &JsValue, _: &[JsValue], context: &mut Context<'_>) -> JsResult<JsValue> {
1124
let Ok(mut file) = OpenOptions::new().write(true).create(true).open(SNAPSHOT_PATH) else {
1225
return Err(JsNativeError::error().with_message("could not create snapshot.bin file").into());
1326
};
1427

15-
let mut serializer = SnapshotSerializer::new();
28+
let serializer = SnapshotSerializer::new();
1629

17-
serializer.serialize(context).unwrap();
30+
let snapshot = serializer.serialize(context).unwrap();
1831

19-
file.write_all(serializer.bytes()).unwrap();
32+
file.write_all(snapshot.bytes()).unwrap();
2033
file.flush().unwrap();
2134

2235
Ok(JsValue::undefined())
2336
}
2437

38+
fn load(_: &JsValue, _: &[JsValue], context: &mut Context<'_>) -> JsResult<JsValue> {
39+
// let Ok(mut file) = OpenOptions::new().read(true).open(SNAPSHOT_PATH) else {
40+
// return Err(JsNativeError::error().with_message("could not open snapshot.bin file").into());
41+
// };
42+
43+
let bytes = get_file_as_byte_vec(SNAPSHOT_PATH);
44+
45+
let snapshot = Snapshot::new(bytes);
46+
47+
let deser_context = snapshot.deserialize().unwrap();
48+
49+
*context = deser_context;
50+
51+
Ok(JsValue::undefined())
52+
}
53+
2554
pub(super) fn create_object(context: &mut Context<'_>) -> JsObject {
2655
ObjectInitializer::new(context)
2756
.function(NativeFunction::from_fn_ptr(create), "create", 0)
57+
.function(NativeFunction::from_fn_ptr(load), "load", 1)
2858
.build()
2959
}

boa_cli/src/main.rs

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ use boa_engine::{
7272
optimizer::OptimizerOptions,
7373
property::Attribute,
7474
script::Script,
75+
snapshot::Snapshot,
7576
vm::flowgraph::{Direction, Graph},
7677
Context, JsError, JsNativeError, JsResult, Source,
7778
};
@@ -81,7 +82,13 @@ use colored::Colorize;
8182
use debug::init_boa_debug_object;
8283
use rustyline::{config::Config, error::ReadlineError, EditMode, Editor};
8384
use std::{
84-
cell::RefCell, collections::VecDeque, eprintln, fs::read, fs::OpenOptions, io, path::PathBuf,
85+
cell::RefCell,
86+
collections::VecDeque,
87+
eprintln,
88+
fs::OpenOptions,
89+
fs::{read, File},
90+
io::{self, Read},
91+
path::{Path, PathBuf},
8592
println,
8693
};
8794

@@ -168,6 +175,9 @@ struct Opt {
168175
/// Root path from where the module resolver will try to load the modules.
169176
#[arg(long, short = 'r', default_value_os_t = PathBuf::from("."), requires = "mod")]
170177
root: PathBuf,
178+
179+
#[arg(long)]
180+
snapshot: Option<PathBuf>,
171181
}
172182

173183
impl Opt {
@@ -363,37 +373,60 @@ fn evaluate_files(
363373
Ok(())
364374
}
365375

376+
fn get_file_as_byte_vec(filename: &Path) -> Vec<u8> {
377+
let mut f = File::open(&filename).expect("no file found");
378+
let metadata = std::fs::metadata(&filename).expect("unable to read metadata");
379+
let mut buffer = vec![0; metadata.len() as usize];
380+
f.read(&mut buffer).expect("buffer overflow");
381+
382+
buffer
383+
}
384+
366385
fn main() -> Result<(), io::Error> {
367386
let args = Opt::parse();
368387

369-
let queue: &dyn JobQueue = &Jobs::default();
370388
let loader = &SimpleModuleLoader::new(&args.root)
371389
.map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))?;
390+
391+
let queue: &dyn JobQueue = &Jobs::default();
372392
let dyn_loader: &dyn ModuleLoader = loader;
373-
let mut context = ContextBuilder::new()
374-
.job_queue(queue)
375-
.module_loader(dyn_loader)
376-
.build()
377-
.expect("cannot fail with default global object");
378393

379-
// Strict mode
380-
context.strict(args.strict);
394+
let mut context = if let Some(path) = &args.snapshot {
395+
let bytes = get_file_as_byte_vec(&path);
381396

382-
// Add `console`.
383-
add_runtime(&mut context);
397+
let snapshot = Snapshot::new(bytes);
384398

385-
// Trace Output
386-
context.set_trace(args.trace);
399+
let deser_context = snapshot.deserialize().unwrap();
387400

388-
if args.debug_object {
389-
init_boa_debug_object(&mut context);
390-
}
401+
deser_context
402+
} else {
403+
let mut context = ContextBuilder::new()
404+
.job_queue(queue)
405+
.module_loader(dyn_loader)
406+
.build()
407+
.expect("cannot fail with default global object");
408+
409+
// Strict mode
410+
context.strict(args.strict);
411+
412+
// Add `console`.
413+
add_runtime(&mut context);
414+
415+
// Trace Output
416+
context.set_trace(args.trace);
391417

392-
// Configure optimizer options
393-
let mut optimizer_options = OptimizerOptions::empty();
394-
optimizer_options.set(OptimizerOptions::STATISTICS, args.optimizer_statistics);
395-
optimizer_options.set(OptimizerOptions::OPTIMIZE_ALL, args.optimize);
396-
context.set_optimizer_options(optimizer_options);
418+
if args.debug_object {
419+
init_boa_debug_object(&mut context);
420+
}
421+
422+
// Configure optimizer options
423+
let mut optimizer_options = OptimizerOptions::empty();
424+
optimizer_options.set(OptimizerOptions::STATISTICS, args.optimizer_statistics);
425+
optimizer_options.set(OptimizerOptions::OPTIMIZE_ALL, args.optimize);
426+
context.set_optimizer_options(optimizer_options);
427+
428+
context
429+
};
397430

398431
if args.files.is_empty() {
399432
let config = Config::builder()

boa_engine/src/context/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,3 +996,16 @@ impl crate::snapshot::Serialize for Context<'_> {
996996
Ok(())
997997
}
998998
}
999+
1000+
impl crate::snapshot::Deserialize for Context<'_> {
1001+
fn deserialize(
1002+
d: &mut crate::snapshot::SnapshotDeserializer<'_>,
1003+
) -> Result<Self, crate::snapshot::SnapshotError> {
1004+
let strict = d.read_bool()?;
1005+
let mut context = Context::default();
1006+
1007+
context.strict(strict);
1008+
1009+
Ok(context)
1010+
}
1011+
}

0 commit comments

Comments
 (0)