1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use crate::{
ast::Identifier,
runtime::{
self,
EvalResult,
Parser,
},
CallContext,
Exception,
Heap,
HeapNode,
HostFn,
Interpretable,
Interpreted,
JSRef,
JSResult,
Program,
};
use serde_json::json;
fn esprima_eval(call: CallContext, heap: &mut Heap) -> JSResult<Interpreted> {
let code = call.arg_value(0, heap)?.stringify(heap)?;
let esprima_ref = (heap.get(Heap::GLOBAL).get_own_value("esprima"))
.ok_or_else(|| Exception::ReferenceNotFound(Identifier::from("esprima")))?
.to_ref()?;
let parse_ref = (heap.get(esprima_ref).get_own_value("parse"))
.ok_or_else(|| {
Exception::TypeErrorGetProperty(Interpreted::from(esprima_ref), "parse".into())
})?
.to_ref()?;
let parser = EsprimaParser {
loc: true,
object: esprima_ref,
esparse: parse_ref,
locflag: Heap::NULL,
};
let program = parser.parse(&code, heap)?;
program.interpret(heap)
}
#[derive(Debug)]
pub struct EsprimaParser {
loc: bool,
object: JSRef,
esparse: JSRef,
locflag: JSRef,
}
impl EsprimaParser {
const ESPRIMA: &'static str = include_str!("../../tmp/esprima.json");
pub fn new() -> Box<Self> {
Box::new(Self {
loc: true,
object: Heap::NULL,
esparse: Heap::NULL,
locflag: Heap::NULL,
})
}
pub fn without_location(mut self: Box<Self>) -> Box<Self> {
self.loc = false;
self
}
}
impl runtime::Parser for EsprimaParser {
fn load(&mut self, heap: &mut Heap) -> EvalResult<()> {
let esprima_json = serde_json::from_str::<serde_json::Value>(Self::ESPRIMA)?;
let esprima = Program::parse_from(&esprima_json).map_err(Exception::SyntaxTreeError)?;
esprima.interpret(heap)?;
let object: JSRef = heap.lookup_path(&["esprima"])?.to_ref(heap)?;
let esparse = (heap.get(object))
.get_own_value("parse")
.ok_or_else(|| Exception::ReferenceNotFound(Identifier::from("esprima.parse")))?
.to_ref()?;
let mut locflag = JSRef::NULL;
if self.loc {
let locjson = json!({ "loc": true });
locflag = heap.object_from_json(&locjson).to_ref()?;
}
self.object = object;
self.esparse = esparse;
self.locflag = locflag;
Ok(())
}
fn parse(&self, input: &str, heap: &mut Heap) -> EvalResult<Program> {
let mut arguments = vec![Interpreted::from(input)];
if self.locflag != Heap::NULL {
arguments.push(Interpreted::from(self.locflag));
}
let estree: Interpreted = heap.execute(
self.esparse,
CallContext::from(arguments)
.with_this(self.object)
.with_name("parse".into()),
)?;
let node = estree.to_ref(heap)?;
let program =
HeapNode::with(heap, node, Program::parse_from).map_err(Exception::SyntaxTreeError)?;
Ok(program)
}
fn eval_func(&self) -> HostFn {
esprima_eval
}
}