Skip to content

Commit 913bb14

Browse files
committed
Merge branch 'master' into wasm-vm-exec_single
2 parents 6436d2c + 8dcea92 commit 913bb14

File tree

7 files changed

+37
-49
lines changed

7 files changed

+37
-49
lines changed

tests/snippets/mro.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@ class C(A, B):
1818
pass
1919

2020
assert (C, A, B, X, Y, object) == C.__mro__
21+
22+
assert type.__mro__ == (type, object)

vm/src/obj/objproperty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ impl<'a, T> PropertyBuilder<'a, T> {
119119
}
120120
}
121121

122-
pub fn add_setter<I, F: IntoPyNativeFunc<(I, T), PyResult>>(self, func: F) -> Self {
122+
pub fn add_setter<I, V, F: IntoPyNativeFunc<(I, V), PyResult>>(self, func: F) -> Self {
123123
let func = self.ctx.new_rustfunc(func);
124124
Self {
125125
ctx: self.ctx,

vm/src/obj/objtype.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::vm::VirtualMachine;
99

1010
use super::objdict;
1111
use super::objlist::PyList;
12+
use super::objproperty::PropertyBuilder;
1213
use super::objstr::{self, PyStringRef};
1314
use super::objtuple::PyTuple;
1415

@@ -78,6 +79,10 @@ impl PyClassRef {
7879
PyTuple::from(elements)
7980
}
8081

82+
fn set_mro(self, _value: PyObjectRef, vm: &mut VirtualMachine) -> PyResult {
83+
Err(vm.new_attribute_error("read-only attribute".to_string()))
84+
}
85+
8186
fn dir(self, vm: &mut VirtualMachine) -> PyList {
8287
let attributes = get_attributes(self);
8388
let attributes: Vec<PyObjectRef> = attributes
@@ -116,7 +121,11 @@ pub fn init(ctx: &PyContext) {
116121
extend_class!(&ctx, &ctx.type_type, {
117122
"__call__" => ctx.new_rustfunc(type_call),
118123
"__new__" => ctx.new_rustfunc(type_new),
119-
"__mro__" => ctx.new_property(PyClassRef::mro),
124+
"__mro__" =>
125+
PropertyBuilder::new(ctx)
126+
.add_getter(PyClassRef::mro)
127+
.add_setter(PyClassRef::set_mro)
128+
.create(),
120129
"__repr__" => ctx.new_rustfunc(PyClassRef::repr),
121130
"__prepare__" => ctx.new_rustfunc(PyClassRef::prepare),
122131
"__getattribute__" => ctx.new_rustfunc(type_getattribute),

wasm/demo/src/main.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,15 @@ function runCodeFromTextarea() {
3636
const code = editor.getValue();
3737
try {
3838
const result = rp.pyEval(code, {
39-
stdout: '#console'
39+
stdout: output => {
40+
const shouldScroll =
41+
consoleElement.scrollHeight - consoleElement.scrollTop ===
42+
consoleElement.clientHeight;
43+
consoleElement.value += output;
44+
if (shouldScroll) {
45+
consoleElement.scrollTop = consoleElement.scrollHeight;
46+
}
47+
}
4048
});
4149
if (result !== null) {
4250
consoleElement.value += `\n${result}\n`;

wasm/lib/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ features = [
2626
"console",
2727
"Document",
2828
"Element",
29-
"HtmlTextAreaElement",
3029
"Window",
3130
"Headers",
3231
"Request",

wasm/lib/src/vm_class.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustpython_vm::{
1111
use std::cell::RefCell;
1212
use std::collections::HashMap;
1313
use std::rc::{Rc, Weak};
14-
use wasm_bindgen::prelude::*;
14+
use wasm_bindgen::{prelude::*, JsCast};
1515

1616
pub trait HeldRcInner {}
1717

@@ -266,13 +266,15 @@ impl WASMVirtualMachine {
266266
#[wasm_bindgen(js_name = setStdout)]
267267
pub fn set_stdout(&self, stdout: JsValue) -> Result<(), JsValue> {
268268
self.with(move |StoredVirtualMachine { ref mut vm, .. }| {
269+
fn error() -> JsValue {
270+
TypeError::new("Unknown stdout option, please pass a function or 'console'").into()
271+
}
269272
let print_fn: Box<Fn(&mut VirtualMachine, PyFuncArgs) -> PyResult> =
270-
if let Some(selector) = stdout.as_string() {
271-
Box::new(
272-
move |vm: &mut VirtualMachine, args: PyFuncArgs| -> PyResult {
273-
wasm_builtins::builtin_print_html(vm, args, &selector)
274-
},
275-
)
273+
if let Some(s) = stdout.as_string() {
274+
match s.as_str() {
275+
"console" => Box::new(wasm_builtins::builtin_print_console),
276+
_ => return Err(error()),
277+
}
276278
} else if stdout.is_function() {
277279
let func = js_sys::Function::from(stdout);
278280
Box::new(
@@ -286,11 +288,12 @@ impl WASMVirtualMachine {
286288
},
287289
)
288290
} else if stdout.is_undefined() || stdout.is_null() {
289-
Box::new(wasm_builtins::builtin_print_console)
291+
fn noop(vm: &mut VirtualMachine, _args: PyFuncArgs) -> PyResult {
292+
Ok(vm.get_none())
293+
}
294+
Box::new(noop)
290295
} else {
291-
return Err(
292-
TypeError::new("stdout must be null, a function or a css selector").into(),
293-
);
296+
return Err(error());
294297
};
295298
let rustfunc = vm.ctx.new_rustfunc(print_fn);
296299
vm.ctx.set_attr(&vm.builtins, "print", rustfunc);

wasm/lib/src/wasm_builtins.rs

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,16 @@
44
//! desktop.
55
//! Implements functions listed here: https://docs.python.org/3/library/builtins.html.
66
7-
use crate::convert;
87
use js_sys::{self, Array};
98
use rustpython_vm::obj::{objstr, objtype};
109
use rustpython_vm::pyobject::{IdProtocol, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
1110
use rustpython_vm::VirtualMachine;
12-
use wasm_bindgen::{prelude::*, JsCast};
13-
use web_sys::{self, console, HtmlTextAreaElement};
11+
use web_sys::{self, console};
1412

1513
pub(crate) fn window() -> web_sys::Window {
1614
web_sys::window().expect("Window to be available")
1715
}
1816

19-
// The HTML id of the textarea element that act as our STDOUT
20-
21-
pub fn print_to_html(text: &str, selector: &str) -> Result<(), JsValue> {
22-
let document = window().document().expect("Document to be available");
23-
let element = document
24-
.query_selector(selector)?
25-
.ok_or_else(|| js_sys::TypeError::new("Couldn't get element"))?;
26-
let textarea = element
27-
.dyn_ref::<HtmlTextAreaElement>()
28-
.ok_or_else(|| js_sys::TypeError::new("Element must be a textarea"))?;
29-
30-
let value = textarea.value();
31-
32-
let scroll_height = textarea.scroll_height();
33-
let scrolled_to_bottom = scroll_height - textarea.scroll_top() == textarea.client_height();
34-
35-
textarea.set_value(&format!("{}{}", value, text));
36-
37-
if scrolled_to_bottom {
38-
textarea.scroll_with_x_and_y(0.0, scroll_height.into());
39-
}
40-
41-
Ok(())
42-
}
43-
4417
pub fn format_print_args(vm: &mut VirtualMachine, args: PyFuncArgs) -> Result<String, PyObjectRef> {
4518
// Handle 'sep' kwarg:
4619
let sep_arg = args
@@ -93,12 +66,6 @@ pub fn format_print_args(vm: &mut VirtualMachine, args: PyFuncArgs) -> Result<St
9366
Ok(output)
9467
}
9568

96-
pub fn builtin_print_html(vm: &mut VirtualMachine, args: PyFuncArgs, selector: &str) -> PyResult {
97-
let output = format_print_args(vm, args)?;
98-
print_to_html(&output, selector).map_err(|err| convert::js_to_py(vm, err))?;
99-
Ok(vm.get_none())
100-
}
101-
10269
pub fn builtin_print_console(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
10370
let arr = Array::new();
10471
for arg in args.args {

0 commit comments

Comments
 (0)