use super::RuntimeError;
#[cfg(feature = "test262-host")]
use super::property::PropertyKey;
use super::runtime::Runtime;
use super::value::ObjectRef;
use super::value::Value;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct EvalOptions {
pub filename: String,
pub transient: bool,
}
impl EvalOptions {
pub fn new(filename: impl Into<String>) -> Self {
EvalOptions {
filename: filename.into(),
transient: false,
}
}
#[must_use]
pub fn transient(mut self) -> Self {
self.transient = true;
self
}
}
impl Default for EvalOptions {
fn default() -> Self {
Self::new(crate::engine::compiler::DEFAULT_EVAL_FILENAME)
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct FunctionBytecodeRef {
function: ObjectRef,
#[cfg(test)]
pub(crate) stack: StackCode,
}
#[cfg(test)]
#[derive(Clone)]
pub(crate) struct StackCode {
pub(crate) root: std::rc::Rc<crate::engine::code::function::UnlinkedFunction>,
pub(crate) path: Vec<usize>,
}
#[cfg(test)]
impl StackCode {
pub(crate) fn function(&self) -> &crate::engine::code::function::UnlinkedFunction {
self.path.iter().fold(&self.root, |function, index| {
function.constants()[*index]
.as_child()
.expect("a child-function constant")
})
}
}
#[cfg(test)]
impl std::fmt::Debug for StackCode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("StackCode")
.field("path", &self.path)
.finish()
}
}
#[cfg(test)]
impl PartialEq for StackCode {
fn eq(&self, other: &Self) -> bool {
std::rc::Rc::ptr_eq(&self.root, &other.root) && self.path == other.path
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ModuleBytecodeRef {
name: String,
}
impl ModuleBytecodeRef {
pub fn name(&self) -> &str {
&self.name
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct QjsHelpers {
pub std: bool,
pub script_args: Option<Vec<String>>,
}
#[derive(Clone)]
pub struct Context {
pub(crate) runtime: Runtime,
}
impl FunctionBytecodeRef {
pub(crate) fn new(
function: ObjectRef,
#[cfg(test)] source: &[u8],
#[cfg(test)] filename: &str,
#[cfg(test)] debug_info: crate::engine::code::debug::DebugInfoMode,
) -> Self {
FunctionBytecodeRef {
function,
#[cfg(test)]
stack: StackCode {
root: std::rc::Rc::new(
crate::engine::compiler::compile_unlinked_script_bytes_with_filename(
source, filename, debug_info,
)
.expect("the script compiled once"),
),
path: Vec::new(),
},
}
}
pub(crate) fn function(&self) -> &ObjectRef {
&self.function
}
}
impl ModuleBytecodeRef {
pub(crate) fn new(name: &str) -> Self {
ModuleBytecodeRef {
name: name.to_owned(),
}
}
}
impl Context {
pub fn new(runtime: &Runtime) -> Self {
runtime.context()
}
pub fn try_clone(&self) -> Result<Self, RuntimeError> {
Ok(self.clone())
}
pub fn runtime(&self) -> &Runtime {
&self.runtime
}
pub fn define_module(
&self,
name: &str,
exports: Vec<(String, Value)>,
) -> Result<(), RuntimeError> {
let mut entry = self.runtime.enter()?;
{
let view = entry.view();
for (_, value) in &exports {
if let Value::Object(ObjectRef { slot })
| Value::Symbol(super::value::SymbolRef { slot }) = value
{
view.own(slot)?;
}
}
}
entry.inner.core.forget_module(name);
self.runtime.shared.modules.borrow_mut().insert(
name.to_owned(),
super::runtime::Preloaded::Synthetic(exports),
);
Ok(())
}
#[cfg(feature = "test262-host")]
pub fn install_test262_host(&mut self) -> Result<ObjectRef, RuntimeError> {
{
let mut entry = self.runtime.enter()?;
entry.inner.core.install_test262_host()?;
}
let global = self.global_object()?;
let key = PropertyKey::from_js_string(crate::engine::value::JsString::from_static("$262"));
match self.get_property(&global, &key)? {
Value::Object(host) => Ok(host),
_ => Err(RuntimeError::Invariant("$262 is an object")),
}
}
}