diff --git a/vm/src/builtins/pysuper.rs b/vm/src/builtins/pysuper.rs index 58c4dc6d0..a456ad854 100644 --- a/vm/src/builtins/pysuper.rs +++ b/vm/src/builtins/pysuper.rs @@ -58,12 +58,31 @@ impl PySuper { vm: &VirtualMachine, ) -> PyResult> { // Get the type: - let typ = if let OptionalArg::Present(ty) = py_type { - ty + let (typ, obj) = if let OptionalArg::Present(ty) = py_type { + (ty, py_obj.unwrap_or_none(vm)) } else { let frame = vm .current_frame() .ok_or_else(|| vm.new_runtime_error("super(): no current frame".to_owned()))?; + + if frame.code.arg_count == 0 { + return Err(vm.new_runtime_error("super(): no arguments".to_owned())); + } + let obj = frame.fastlocals.lock()[0] + .clone() + .or_else(|| { + if let Some(cell2arg) = frame.code.cell2arg.as_deref() { + cell2arg[..frame.code.cellvars.len()] + .iter() + .enumerate() + .find(|(_, arg_idx)| **arg_idx == 0) + .and_then(|(cell_idx, _)| frame.cells_frees[cell_idx].get()) + } else { + None + } + }) + .ok_or_else(|| vm.new_runtime_error("super(): arg[0] deleted".to_owned()))?; + let mut typ = None; for (i, var) in frame.code.freevars.iter().enumerate() { if var.borrow_value() == "__class__" { @@ -80,46 +99,13 @@ impl PySuper { break; } } - typ.ok_or_else(|| { + let typ = typ.ok_or_else(|| { vm.new_type_error( "super must be called with 1 argument or from inside class method".to_owned(), ) - })? - }; + })?; - // Check type argument: - if !typ.as_object().isinstance(&vm.ctx.types.type_type) { - return Err(vm.new_type_error(format!( - "super() argument 1 must be type, not {}", - typ.class().name - ))); - } - - // Get the bound object: - let obj = if let OptionalArg::Present(obj) = py_obj { - obj - } else { - let frame = vm - .current_frame() - .ok_or_else(|| vm.new_runtime_error("super(): no current frame".to_owned()))?; - if frame.code.arg_count == 0 { - return Err(vm.new_runtime_error("super(): no arguments".to_owned())); - } - let fastlocals = frame.fastlocals.lock(); - fastlocals[0] - .clone() - .or_else(|| { - if let Some(cell2arg) = frame.code.cell2arg.as_deref() { - cell2arg[..frame.code.cellvars.len()] - .iter() - .enumerate() - .find(|(_, arg_idx)| **arg_idx == 0) - .and_then(|(cell_idx, _)| frame.cells_frees[cell_idx].get()) - } else { - None - } - }) - .ok_or_else(|| vm.new_runtime_error("super(): arg[0] deleted".to_owned()))? + (typ, obj) }; PySuper::new(typ, obj, vm)?.into_ref_with_type(vm, cls) diff --git a/vm/src/frame.rs b/vm/src/frame.rs index 872eed95c..aebf2816c 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -537,11 +537,25 @@ impl ExecutingFrame<'_> { Ok(None) } bytecode::Instruction::DeleteLocal(idx) => { - self.locals.del_item(self.code.names[*idx].clone(), vm)?; + let name = &self.code.names[*idx]; + match self.locals.del_item(name.clone(), vm) { + Ok(()) => {} + Err(e) if e.isinstance(&vm.ctx.exceptions.key_error) => { + return Err(vm.new_name_error(format!("name '{}' is not defined", name))) + } + Err(e) => return Err(e), + } Ok(None) } bytecode::Instruction::DeleteGlobal(idx) => { - self.globals.del_item(self.code.names[*idx].clone(), vm)?; + let name = &self.code.names[*idx]; + match self.globals.del_item(name.clone(), vm) { + Ok(()) => {} + Err(e) if e.isinstance(&vm.ctx.exceptions.key_error) => { + return Err(vm.new_name_error(format!("name '{}' is not defined", name))) + } + Err(e) => return Err(e), + } Ok(None) } bytecode::Instruction::DeleteDeref(i) => { diff --git a/wasm/lib/src/vm_class.rs b/wasm/lib/src/vm_class.rs index 35fc59f13..edb62ff2a 100644 --- a/wasm/lib/src/vm_class.rs +++ b/wasm/lib/src/vm_class.rs @@ -17,7 +17,7 @@ use crate::wasm_builtins; pub(crate) struct StoredVirtualMachine { pub interp: Interpreter, - pub scope: RefCell, + pub scope: Scope, /// you can put a Rc in here, keep it as a Weak, and it'll be held only for /// as long as the StoredVM is alive held_objects: RefCell>, @@ -47,7 +47,7 @@ impl StoredVirtualMachine { StoredVirtualMachine { interp, - scope: RefCell::new(scope.unwrap()), + scope: scope.unwrap(), held_objects: RefCell::new(Vec::new()), } } @@ -203,8 +203,8 @@ impl WASMVirtualMachine { pub fn add_to_scope(&self, name: String, value: JsValue) -> Result<(), JsValue> { self.with_vm(move |vm, StoredVirtualMachine { ref scope, .. }| { let value = convert::js_to_py(vm, value); - scope.borrow_mut().store_name(&vm, name.as_str(), value); - }) + scope.globals.set_item(name, value, vm).to_js(vm) + })? } #[wasm_bindgen(js_name = setStdout)] @@ -264,7 +264,7 @@ impl WASMVirtualMachine { } } - vm.run_code_obj(code, Scope::new(None, attrs.clone(), vm)) + vm.run_code_obj(code, Scope::new(None, attrs.clone())) .to_js(vm)?; let module = vm.new_module(&name, attrs); @@ -309,7 +309,7 @@ impl WASMVirtualMachine { let source_path = source_path.unwrap_or_else(|| "".to_owned()); let code = vm.compile(source, mode, source_path); let code = code.map_err(convert::syntax_err)?; - let result = vm.run_code_obj(code, scope.borrow().clone()); + let result = vm.run_code_obj(code, scope.clone()); convert::pyresult_to_jsresult(vm, result) })? }