1use crate::{future_wrapper, rc_fn_helper, LazyBinding, ObjValue, LazyVal, Val};2use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc};34rc_fn_helper!(5 ContextCreator,6 context_creator,7 dyn Fn(Option<ObjValue>, Option<ObjValue>) -> Context8);910future_wrapper!(Context, FutureContext);1112#[derive(Debug)]13struct ContextInternals {14 dollar: Option<ObjValue>,15 this: Option<ObjValue>,16 super_obj: Option<ObjValue>,17 bindings: Rc<HashMap<String, LazyVal>>,18}19pub struct Context(Rc<ContextInternals>);20impl Debug for Context {21 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {22 f.debug_struct("Context")23 .field("this", &self.0.this.clone().map(|e| Rc::as_ptr(&e.0)))24 .finish()25 }26}27impl Context {28 pub fn new_future() -> FutureContext {29 FutureContext(Rc::new(RefCell::new(None)))30 }3132 pub fn dollar(&self) -> &Option<ObjValue> {33 &self.0.dollar34 }3536 pub fn this(&self) -> &Option<ObjValue> {37 &self.0.this38 }3940 pub fn super_obj(&self) -> &Option<ObjValue> {41 &self.0.super_obj42 }4344 pub fn new() -> Context {45 Context(Rc::new(ContextInternals {46 dollar: None,47 this: None,48 super_obj: None,49 bindings: Rc::new(HashMap::new()),50 }))51 }5253 pub fn binding(&self, name: &str) -> LazyVal {54 self.055 .bindings56 .get(name)57 .cloned()58 .unwrap_or_else(|| {59 panic!("can't find {} in {:?}", name, self);60 })61 }62 pub fn into_future(self, ctx: FutureContext) -> Context {63 {64 ctx.0.borrow_mut().replace(self);65 }66 ctx.unwrap()67 }6869 pub fn extend(70 &self,71 new_bindings: HashMap<String, LazyBinding>,72 new_dollar: Option<ObjValue>,73 new_this: Option<ObjValue>,74 new_super_obj: Option<ObjValue>,75 ) -> Context {76 let dollar = new_dollar.or_else(|| self.0.dollar.clone());77 let this = new_this.or_else(|| self.0.this.clone());78 let super_obj = new_super_obj.or_else(|| self.0.super_obj.clone());79 let bindings = if new_bindings.is_empty() {80 self.0.bindings.clone()81 } else {82 let mut new = HashMap::new(); 83 for (k, v) in self.0.bindings.iter() {84 new.insert(k.clone(), v.clone());85 }86 for (k, v) in new_bindings.into_iter() {87 new.insert(k, v.0(this.clone(), super_obj.clone()));88 }89 Rc::new(new)90 };91 Context(Rc::new(ContextInternals {92 dollar,93 this,94 super_obj,95 bindings,96 }))97 }98}99100impl Default for Context {101 fn default() -> Self {102 Self::new()103 }104}105106impl PartialEq for Context {107 fn eq(&self, other: &Self) -> bool {108 Rc::ptr_eq(&self.0, &other.0)109 }110}111112impl Clone for Context {113 fn clone(&self) -> Self {114 Context(self.0.clone())115 }116}