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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use std::{cell::RefCell, rc::Rc};
use super::ByteCompiler;
use crate::environments::{BindingLocator, BindingLocatorError, CompileTimeEnvironment};
use boa_ast::expression::Identifier;
impl ByteCompiler<'_, '_> {
/// Push either a new declarative or function environment on the compile time environment stack.
pub(crate) fn push_compile_environment(&mut self, function_scope: bool) {
self.current_environment = Rc::new(RefCell::new(CompileTimeEnvironment::new(
self.current_environment.clone(),
function_scope,
)));
}
/// Pops the top compile time environment and returns its index in the compile time environments array.
#[track_caller]
pub(crate) fn pop_compile_environment(&mut self) -> u32 {
let index = self.compile_environments.len() as u32;
self.compile_environments
.push(self.current_environment.clone());
let outer = {
let env = self.current_environment.borrow();
env.outer().expect("cannot pop the global environment")
};
self.current_environment = outer;
index
}
/// Get the binding locator of the binding at bytecode compile time.
pub(crate) fn get_binding_value(&self, name: Identifier) -> BindingLocator {
self.current_environment
.borrow()
.get_binding_recursive(name)
}
/// Return if a declarative binding exists at bytecode compile time.
/// This does not include bindings on the global object.
pub(crate) fn has_binding(&self, name: Identifier) -> bool {
self.current_environment
.borrow()
.has_binding_recursive(name)
}
/// Check if a binding name exists in a environment.
/// If strict is `false` check until a function scope is reached.
pub(crate) fn has_binding_eval(&self, name: Identifier, strict: bool) -> bool {
self.current_environment
.borrow()
.has_binding_eval(name, strict)
}
#[cfg(feature = "annex-b")]
/// Check if a binding name exists in a environment.
/// Stop when a function scope is reached.
pub(crate) fn has_binding_until_var(&self, name: Identifier) -> bool {
self.current_environment
.borrow()
.has_binding_until_var(name)
}
/// Create a mutable binding at bytecode compile time.
/// This function returns a syntax error, if the binding is a redeclaration.
///
/// # Panics
///
/// Panics if the global environment is not function scoped.
pub(crate) fn create_mutable_binding(&mut self, name: Identifier, function_scope: bool) {
assert!(self
.current_environment
.borrow_mut()
.create_mutable_binding(name, function_scope));
}
/// Initialize a mutable binding at bytecode compile time and return its binding locator.
pub(crate) fn initialize_mutable_binding(
&self,
name: Identifier,
function_scope: bool,
) -> BindingLocator {
self.current_environment
.borrow()
.initialize_mutable_binding(name, function_scope)
}
/// Create an immutable binding at bytecode compile time.
/// This function returns a syntax error, if the binding is a redeclaration.
///
/// # Panics
///
/// Panics if the global environment does not exist.
pub(crate) fn create_immutable_binding(&mut self, name: Identifier, strict: bool) {
self.current_environment
.borrow_mut()
.create_immutable_binding(name, strict);
}
/// Initialize an immutable binding at bytecode compile time and return it's binding locator.
///
/// # Panics
///
/// Panics if the global environment does not exist or a the binding was not created on the current environment.
pub(crate) fn initialize_immutable_binding(&self, name: Identifier) -> BindingLocator {
self.current_environment
.borrow()
.initialize_immutable_binding(name)
}
/// Return the binding locator for a set operation on an existing binding.
pub(crate) fn set_mutable_binding(
&self,
name: Identifier,
) -> Result<BindingLocator, BindingLocatorError> {
self.current_environment
.borrow()
.set_mutable_binding_recursive(name)
}
#[cfg(feature = "annex-b")]
/// Return the binding locator for a set operation on an existing var binding.
pub(crate) fn set_mutable_binding_var(
&self,
name: Identifier,
) -> Result<BindingLocator, BindingLocatorError> {
self.current_environment
.borrow()
.set_mutable_binding_var_recursive(name)
}
}