mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Fix merge conflicts
This commit is contained in:
commit
e3db472f37
22 files changed
+237
-42
No files matched your search
Generated
+1
@@ -775,6 +775,7 @@ dependencies = [
|
||||
"cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"js-sys 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustpython_parser 0.0.1",
|
||||
"rustpython_vm 0.1.0",
|
||||
"wasm-bindgen 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
||||
+5
-2
@@ -55,6 +55,7 @@ pub struct Lexer<T: Iterator<Item = char>> {
|
||||
pub enum LexicalError {
|
||||
StringError,
|
||||
NestingError,
|
||||
UnrecognizedToken { tok: char },
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
@@ -687,7 +688,9 @@ where
|
||||
|
||||
match self.chr0 {
|
||||
Some('0'..='9') => return Some(self.lex_number()),
|
||||
Some('_') | Some('a'..='z') | Some('A'..='Z') => return Some(self.lex_identifier()),
|
||||
Some('_') | Some('a'..='z') | Some('A'..='Z') => {
|
||||
return Some(self.lex_identifier());
|
||||
}
|
||||
Some('#') => {
|
||||
self.lex_comment();
|
||||
continue;
|
||||
@@ -1033,7 +1036,7 @@ where
|
||||
None => return None,
|
||||
_ => {
|
||||
let c = self.next_char();
|
||||
panic!("Not impl {:?}", c)
|
||||
return Some(Err(LexicalError::UnrecognizedToken { tok: c.unwrap() }));
|
||||
} // Ignore all the rest..
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,7 +306,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_class() {
|
||||
let source = String::from("class Foo(A, B):\n def __init__(self):\n pass\n def method_with_default(self, arg='default'):\n pass\n");
|
||||
let source = String::from(
|
||||
"class Foo(A, B):\n def __init__(self):\n pass\n def method_with_default(self, arg='default'):\n pass\n",
|
||||
);
|
||||
assert_eq!(
|
||||
parse_statement(&source),
|
||||
Ok(ast::LocatedStatement {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
edition = "2018"
|
||||
@@ -1,3 +1,5 @@
|
||||
from testutils import assert_raises
|
||||
|
||||
# int to int comparisons
|
||||
|
||||
assert 1 == 1
|
||||
@@ -36,6 +38,7 @@ assert (2).__rtruediv__(1) == 0.5
|
||||
assert (1).real == 1
|
||||
assert (1).imag == 0
|
||||
|
||||
assert_raises(OverflowError, lambda: 1 << 10 ** 100000)
|
||||
|
||||
assert (1).__eq__(1.0) == NotImplemented
|
||||
assert (1).__ne__(1.0) == NotImplemented
|
||||
|
||||
@@ -117,3 +117,42 @@ b.append(c)
|
||||
assert a == b
|
||||
|
||||
assert [foo] == [foo]
|
||||
|
||||
for size in [1, 2, 3, 4, 5, 8, 10, 100, 1000]:
|
||||
lst = list(range(size))
|
||||
orig = lst[:]
|
||||
lst.sort()
|
||||
assert lst == orig
|
||||
assert sorted(lst) == orig
|
||||
assert_raises(ZeroDivisionError, lambda: sorted(lst, key=lambda x: 1/x))
|
||||
lst.reverse()
|
||||
assert sorted(lst) == orig
|
||||
assert sorted(lst, reverse=True) == lst
|
||||
assert sorted(lst, key=lambda x: -x) == lst
|
||||
assert sorted(lst, key=lambda x: -x, reverse=True) == orig
|
||||
|
||||
assert sorted([(1, 2, 3), (0, 3, 6)]) == [(0, 3, 6), (1, 2, 3)]
|
||||
assert sorted([(1, 2, 3), (0, 3, 6)], key=lambda x: x[0]) == [(0, 3, 6), (1, 2, 3)]
|
||||
assert sorted([(1, 2, 3), (0, 3, 6)], key=lambda x: x[1]) == [(1, 2, 3), (0, 3, 6)]
|
||||
assert sorted([(1, 2), (), (5,)], key=len) == [(), (5,), (1, 2)]
|
||||
|
||||
lst = [3, 1, 5, 2, 4]
|
||||
class C:
|
||||
def __init__(self, x): self.x = x
|
||||
def __lt__(self, other): return self.x < other.x
|
||||
lst.sort(key=C)
|
||||
assert lst == [1, 2, 3, 4, 5]
|
||||
|
||||
lst = [3, 1, 5, 2, 4]
|
||||
class C:
|
||||
def __init__(self, x): self.x = x
|
||||
def __gt__(self, other): return self.x > other.x
|
||||
lst.sort(key=C)
|
||||
assert lst == [1, 2, 3, 4, 5]
|
||||
|
||||
lst = [5, 1, 2, 3, 4]
|
||||
def f(x):
|
||||
lst.append(1)
|
||||
return x
|
||||
assert_raises(ValueError, lambda: lst.sort(key=f)) # "list modified during sort"
|
||||
assert lst == [1, 2, 3, 4, 5]
|
||||
+11
-1
@@ -689,7 +689,16 @@ fn builtin_setattr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
// builtin_slice
|
||||
// builtin_sorted
|
||||
|
||||
fn builtin_sorted(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(iterable, None)]);
|
||||
let items = vm.extract_elements(iterable)?;
|
||||
let lst = vm.ctx.new_list(items);
|
||||
|
||||
args.shift();
|
||||
vm.call_method_pyargs(&lst, "sort", args)?;
|
||||
Ok(lst)
|
||||
}
|
||||
|
||||
fn builtin_sum(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(iterable, None)]);
|
||||
@@ -763,6 +772,7 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef {
|
||||
"round" => ctx.new_rustfunc(builtin_round),
|
||||
"set" => ctx.set_type(),
|
||||
"setattr" => ctx.new_rustfunc(builtin_setattr),
|
||||
"sorted" => ctx.new_rustfunc(builtin_sorted),
|
||||
"slice" => ctx.slice_type(),
|
||||
"staticmethod" => ctx.staticmethod_type(),
|
||||
"str" => ctx.str_type(),
|
||||
|
||||
+1
-1
@@ -1389,7 +1389,7 @@ impl Compiler {
|
||||
// Low level helper functions:
|
||||
fn emit(&mut self, instruction: Instruction) {
|
||||
let location = self.current_source_location.clone();
|
||||
let mut cur_code_obj = self.current_code_object();
|
||||
let cur_code_obj = self.current_code_object();
|
||||
cur_code_obj.instructions.push(instruction);
|
||||
cur_code_obj.locations.push(location);
|
||||
// TODO: insert source filename
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ pub fn import_module(
|
||||
return Ok(module);
|
||||
}
|
||||
let module = import_uncached_module(vm, current_path, module_name)?;
|
||||
vm.ctx.set_item(&sys_modules, module_name, module.clone());
|
||||
sys_modules.set_item(&vm.ctx, module_name, module.clone());
|
||||
Ok(module)
|
||||
}
|
||||
|
||||
|
||||
@@ -246,8 +246,7 @@ fn int_lshift(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
match get_value(i2) {
|
||||
ref v if *v < BigInt::zero() => Err(vm.new_value_error("negative shift count".to_string())),
|
||||
ref v if *v > BigInt::from(usize::max_value()) => {
|
||||
// TODO: raise OverflowError
|
||||
panic!("Failed converting {} to rust usize", get_value(i2));
|
||||
Err(vm.new_overflow_error("the number is too large to convert to int".to_string()))
|
||||
}
|
||||
_ => panic!("Failed converting {} to rust usize", get_value(i2)),
|
||||
}
|
||||
@@ -276,8 +275,7 @@ fn int_rshift(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
match get_value(i2) {
|
||||
ref v if *v < BigInt::zero() => Err(vm.new_value_error("negative shift count".to_string())),
|
||||
ref v if *v > BigInt::from(usize::max_value()) => {
|
||||
// TODO: raise OverflowError
|
||||
panic!("Failed converting {} to rust usize", get_value(i2));
|
||||
Err(vm.new_overflow_error("the number is too large to convert to int".to_string()))
|
||||
}
|
||||
_ => panic!("Failed converting {} to rust usize", get_value(i2)),
|
||||
}
|
||||
|
||||
+93
-6
@@ -3,8 +3,8 @@ use std::cell::{Cell, RefCell};
|
||||
use super::objbool;
|
||||
use super::objint;
|
||||
use super::objsequence::{
|
||||
get_elements, get_item, get_mut_elements, seq_equal, seq_ge, seq_gt, seq_le, seq_lt, seq_mul,
|
||||
PySliceableSequence,
|
||||
get_elements, get_elements_cell, get_item, get_mut_elements, seq_equal, seq_ge, seq_gt, seq_le,
|
||||
seq_lt, seq_mul, PySliceableSequence,
|
||||
};
|
||||
use super::objstr;
|
||||
use super::objtype;
|
||||
@@ -334,12 +334,99 @@ fn list_reverse(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
|
||||
fn quicksort(
|
||||
vm: &mut VirtualMachine,
|
||||
keys: &mut [PyObjectRef],
|
||||
values: &mut [PyObjectRef],
|
||||
) -> PyResult<()> {
|
||||
let len = values.len();
|
||||
if len >= 2 {
|
||||
let pivot = partition(vm, keys, values)?;
|
||||
quicksort(vm, &mut keys[0..pivot], &mut values[0..pivot])?;
|
||||
quicksort(vm, &mut keys[pivot + 1..len], &mut values[pivot + 1..len])?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn partition(
|
||||
vm: &mut VirtualMachine,
|
||||
keys: &mut [PyObjectRef],
|
||||
values: &mut [PyObjectRef],
|
||||
) -> PyResult<usize> {
|
||||
let len = values.len();
|
||||
let pivot = len / 2;
|
||||
|
||||
values.swap(pivot, len - 1);
|
||||
keys.swap(pivot, len - 1);
|
||||
|
||||
let mut store_idx = 0;
|
||||
for i in 0..len - 1 {
|
||||
let result = vm._lt(keys[i].clone(), keys[len - 1].clone())?;
|
||||
let boolval = objbool::boolval(vm, result)?;
|
||||
if boolval {
|
||||
values.swap(i, store_idx);
|
||||
keys.swap(i, store_idx);
|
||||
store_idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
values.swap(store_idx, len - 1);
|
||||
keys.swap(store_idx, len - 1);
|
||||
Ok(store_idx)
|
||||
}
|
||||
|
||||
fn do_sort(
|
||||
vm: &mut VirtualMachine,
|
||||
values: &mut Vec<PyObjectRef>,
|
||||
key_func: Option<PyObjectRef>,
|
||||
reverse: bool,
|
||||
) -> PyResult<()> {
|
||||
// build a list of keys. If no keyfunc is provided, it's a copy of the list.
|
||||
let mut keys: Vec<PyObjectRef> = vec![];
|
||||
for x in values.iter() {
|
||||
keys.push(match &key_func {
|
||||
None => x.clone(),
|
||||
Some(ref func) => vm.invoke(
|
||||
(*func).clone(),
|
||||
PyFuncArgs {
|
||||
args: vec![x.clone()],
|
||||
kwargs: vec![],
|
||||
},
|
||||
)?,
|
||||
});
|
||||
}
|
||||
|
||||
quicksort(vm, &mut keys, values)?;
|
||||
|
||||
if reverse {
|
||||
values.reverse();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn list_sort(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(list, Some(vm.ctx.list_type()))]);
|
||||
let mut _elements = get_mut_elements(list);
|
||||
unimplemented!("TODO: figure out how to invoke `sort_by` on a Vec");
|
||||
// elements.sort_by();
|
||||
// Ok(vm.get_none())
|
||||
let key_func = args.get_optional_kwarg("key");
|
||||
let reverse = args.get_optional_kwarg("reverse");
|
||||
let reverse = match reverse {
|
||||
None => false,
|
||||
Some(val) => objbool::boolval(vm, val)?,
|
||||
};
|
||||
|
||||
let elements_cell = get_elements_cell(list);
|
||||
// replace list contents with [] for duration of sort.
|
||||
// this prevents keyfunc from messing with the list and makes it easy to
|
||||
// check if it tries to append elements to it.
|
||||
let mut elements = elements_cell.replace(vec![]);
|
||||
do_sort(vm, &mut elements, key_func, reverse)?;
|
||||
let temp_elements = elements_cell.replace(elements);
|
||||
|
||||
if !temp_elements.is_empty() {
|
||||
return Err(vm.new_value_error("list modified during sort".to_string()));
|
||||
}
|
||||
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
|
||||
fn list_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use super::objstr;
|
||||
use super::objtype;
|
||||
use crate::pyobject::{
|
||||
AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef,
|
||||
PyResult, TypeProtocol,
|
||||
AttributeProtocol, DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload,
|
||||
PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
use std::cell::RefCell;
|
||||
@@ -182,7 +182,7 @@ fn object_dict(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
PyObjectPayload::Class { ref dict, .. } | PyObjectPayload::Instance { ref dict, .. } => {
|
||||
let new_dict = vm.new_dict();
|
||||
for (attr, value) in dict.borrow().iter() {
|
||||
vm.ctx.set_item(&new_dict, &attr, value.clone());
|
||||
new_dict.set_item(&vm.ctx, &attr, value.clone());
|
||||
}
|
||||
Ok(new_dict)
|
||||
}
|
||||
|
||||
@@ -302,6 +302,14 @@ pub fn seq_mul(elements: &[PyObjectRef], product: &PyObjectRef) -> Vec<PyObjectR
|
||||
new_elements
|
||||
}
|
||||
|
||||
pub fn get_elements_cell<'a>(obj: &'a PyObjectRef) -> &'a RefCell<Vec<PyObjectRef>> {
|
||||
if let PyObjectPayload::Sequence { ref elements } = obj.payload {
|
||||
elements
|
||||
} else {
|
||||
panic!("Cannot extract elements from non-sequence");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_elements<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<PyObjectRef>> + 'a {
|
||||
if let PyObjectPayload::Sequence { ref elements } = obj.payload {
|
||||
elements.borrow()
|
||||
|
||||
+20
-1
@@ -833,6 +833,7 @@ pub trait DictProtocol {
|
||||
fn contains_key(&self, k: &str) -> bool;
|
||||
fn get_item(&self, k: &str) -> Option<PyObjectRef>;
|
||||
fn get_key_value_pairs(&self) -> Vec<(PyObjectRef, PyObjectRef)>;
|
||||
fn set_item(&self, ctx: &PyContext, key: &str, v: PyObjectRef);
|
||||
}
|
||||
|
||||
impl DictProtocol for PyObjectRef {
|
||||
@@ -851,8 +852,9 @@ impl DictProtocol for PyObjectRef {
|
||||
PyObjectPayload::Dict { ref elements } => {
|
||||
objdict::content_get_key_str(&elements.borrow(), k)
|
||||
}
|
||||
PyObjectPayload::Module { ref dict, .. } => dict.get_item(k),
|
||||
PyObjectPayload::Scope { ref scope } => scope.borrow().locals.get_item(k),
|
||||
_ => panic!("TODO"),
|
||||
ref k => panic!("TODO {:?}", k),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -864,6 +866,23 @@ impl DictProtocol for PyObjectRef {
|
||||
_ => panic!("TODO"),
|
||||
}
|
||||
}
|
||||
|
||||
// Item set/get:
|
||||
fn set_item(&self, ctx: &PyContext, key: &str, v: PyObjectRef) {
|
||||
match &self.payload {
|
||||
PyObjectPayload::Dict { elements } => {
|
||||
let key = ctx.new_str(key.to_string());
|
||||
objdict::set_item_in_content(&mut elements.borrow_mut(), &key, &v);
|
||||
}
|
||||
PyObjectPayload::Module { dict, .. } => {
|
||||
dict.set_item(ctx, key, v);
|
||||
}
|
||||
PyObjectPayload::Scope { scope, .. } => {
|
||||
scope.borrow().locals.set_item(ctx, key, v);
|
||||
}
|
||||
ref k => panic!("TODO {:?}", k),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub trait BufferProtocol {
|
||||
|
||||
@@ -171,7 +171,7 @@ impl<'de> Visitor<'de> for PyObjectDeserializer<'de> {
|
||||
PyObjectPayload::String { ref value } => value.clone(),
|
||||
_ => unimplemented!("map keys must be strings"),
|
||||
};
|
||||
self.vm.ctx.set_item(&dict, &key, value);
|
||||
dict.set_item(&self.vm.ctx, &key, value);
|
||||
}
|
||||
Ok(dict)
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use crate::pyobject::{DictProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use crate::vm::VirtualMachine;
|
||||
use std::rc::Rc;
|
||||
use std::{env, mem};
|
||||
@@ -132,7 +132,7 @@ settrace() -- set the global debug tracing function
|
||||
"_getframe" => ctx.new_rustfunc(getframe),
|
||||
});
|
||||
|
||||
ctx.set_item(&modules, sys_name, sys_mod.clone());
|
||||
modules.set_item(&ctx, sys_name, sys_mod.clone());
|
||||
ctx.set_attr(&sys_mod, "modules", modules);
|
||||
|
||||
sys_mod
|
||||
|
||||
+8
-2
@@ -26,6 +26,7 @@ use crate::pyobject::{
|
||||
};
|
||||
use crate::stdlib;
|
||||
use crate::sysmodule;
|
||||
use num_bigint::ToBigInt;
|
||||
|
||||
// use objects::objects;
|
||||
|
||||
@@ -53,7 +54,7 @@ impl VirtualMachine {
|
||||
|
||||
// Add builtins as builtins module:
|
||||
let modules = sysmod.get_attr("modules").unwrap();
|
||||
ctx.set_item(&modules, "builtins", builtins.clone());
|
||||
modules.set_item(&ctx, "builtins", builtins.clone());
|
||||
|
||||
let stdlib_inits = stdlib::get_module_inits();
|
||||
VirtualMachine {
|
||||
@@ -76,6 +77,11 @@ impl VirtualMachine {
|
||||
self.ctx.new_str(s)
|
||||
}
|
||||
|
||||
/// Create a new python int object.
|
||||
pub fn new_int<T: ToBigInt>(&self, i: T) -> PyObjectRef {
|
||||
self.ctx.new_int(i)
|
||||
}
|
||||
|
||||
/// Create a new python bool object.
|
||||
pub fn new_bool(&self, b: bool) -> PyObjectRef {
|
||||
self.ctx.new_bool(b)
|
||||
@@ -395,7 +401,7 @@ impl VirtualMachine {
|
||||
|
||||
self.ctx.set_attr(scope, &name, value);
|
||||
} else if let Some(d) = &kwargs {
|
||||
self.ctx.set_item(d, &name, value);
|
||||
d.set_item(&self.ctx, &name, value);
|
||||
} else {
|
||||
return Err(
|
||||
self.new_type_error(format!("Got an unexpected keyword argument '{}'", name))
|
||||
|
||||
+15
-9
@@ -12,7 +12,11 @@ const editor = CodeMirror.fromTextArea(document.getElementById('code'), {
|
||||
'Cmd-Enter': runCodeFromTextarea,
|
||||
'Shift-Tab': 'indentLess',
|
||||
'Ctrl-/': 'toggleComment',
|
||||
'Cmd-/': 'toggleComment'
|
||||
'Cmd-/': 'toggleComment',
|
||||
Tab: editor => {
|
||||
var spaces = Array(editor.getOption('indentUnit') + 1).join(' ');
|
||||
editor.replaceSelection(spaces);
|
||||
}
|
||||
},
|
||||
lineNumbers: true,
|
||||
mode: 'text/x-python',
|
||||
@@ -20,10 +24,10 @@ const editor = CodeMirror.fromTextArea(document.getElementById('code'), {
|
||||
autofocus: true
|
||||
});
|
||||
|
||||
function runCodeFromTextarea() {
|
||||
const consoleElement = document.getElementById('console');
|
||||
const errorElement = document.getElementById('error');
|
||||
const consoleElement = document.getElementById('console');
|
||||
const errorElement = document.getElementById('error');
|
||||
|
||||
function runCodeFromTextarea() {
|
||||
// Clean the console and errors
|
||||
consoleElement.value = '';
|
||||
errorElement.textContent = '';
|
||||
@@ -51,7 +55,7 @@ document
|
||||
|
||||
const snippets = document.getElementById('snippets');
|
||||
|
||||
snippets.addEventListener('change', () => {
|
||||
const updateSnippet = () => {
|
||||
const selected = snippets.value;
|
||||
|
||||
// the require here creates a webpack context; it's fine to use it
|
||||
@@ -60,9 +64,11 @@ snippets.addEventListener('change', () => {
|
||||
const snippet = require(`raw-loader!../snippets/${selected}.py`);
|
||||
|
||||
editor.setValue(snippet);
|
||||
|
||||
runCodeFromTextarea();
|
||||
});
|
||||
};
|
||||
|
||||
// Run once for demo
|
||||
runCodeFromTextarea();
|
||||
snippets.addEventListener('change', updateSnippet);
|
||||
|
||||
// Run once for demo (updateSnippet b/c the browser might try to keep the same
|
||||
// option selected for the `select`, but the textarea won't be updated)
|
||||
updateSnippet();
|
||||
@@ -18,6 +18,7 @@ wasm-bindgen = "0.2"
|
||||
wasm-bindgen-futures = "0.3"
|
||||
js-sys = "0.3"
|
||||
futures = "0.1"
|
||||
num-traits = "0.2"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::{convert, vm_class::AccessibleVM, wasm_builtins::window};
|
||||
use futures::Future;
|
||||
use js_sys::Promise;
|
||||
use num_traits::cast::ToPrimitive;
|
||||
use rustpython_vm::obj::{objint, objstr};
|
||||
use rustpython_vm::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
@@ -139,11 +140,12 @@ fn browser_request_animation_frame(vm: &mut VirtualMachine, args: PyFuncArgs) ->
|
||||
fn browser_cancel_animation_frame(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(id, Some(vm.ctx.int_type()))]);
|
||||
|
||||
// questionable, but it's probably fine
|
||||
let id = objint::get_value(id)
|
||||
.to_string()
|
||||
.parse()
|
||||
.expect("bigint.to_string() to be parsable as i32");
|
||||
let id = objint::get_value(id).to_i32().ok_or_else(|| {
|
||||
vm.new_exception(
|
||||
vm.ctx.exceptions.value_error.clone(),
|
||||
"Integer too large to convert to i32 for animationFrame id".into(),
|
||||
)
|
||||
})?;
|
||||
|
||||
window()
|
||||
.cancel_animation_frame(id)
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::browser_module;
|
||||
use crate::vm_class::{AccessibleVM, WASMVirtualMachine};
|
||||
use js_sys::{Array, ArrayBuffer, Object, Promise, Reflect, Uint8Array};
|
||||
use rustpython_vm::obj::{objbytes, objtype};
|
||||
use rustpython_vm::pyobject::{self, PyFuncArgs, PyObjectRef, PyResult};
|
||||
use rustpython_vm::pyobject::{self, DictProtocol, PyFuncArgs, PyObjectRef, PyResult};
|
||||
use rustpython_vm::VirtualMachine;
|
||||
use wasm_bindgen::{closure::Closure, prelude::*, JsCast};
|
||||
|
||||
@@ -147,8 +147,7 @@ pub fn js_to_py(vm: &mut VirtualMachine, js_val: JsValue) -> PyObjectRef {
|
||||
for pair in object_entries(&Object::from(js_val)) {
|
||||
let (key, val) = pair.expect("iteration over object to not fail");
|
||||
let py_val = js_to_py(vm, val);
|
||||
vm.ctx
|
||||
.set_item(&dict, &String::from(js_sys::JsString::from(key)), py_val);
|
||||
dict.set_item(&vm.ctx, &String::from(js_sys::JsString::from(key)), py_val);
|
||||
}
|
||||
dict
|
||||
}
|
||||
|
||||
@@ -26,8 +26,18 @@ pub fn print_to_html(text: &str, selector: &str) -> Result<(), JsValue> {
|
||||
let textarea = element
|
||||
.dyn_ref::<HtmlTextAreaElement>()
|
||||
.ok_or_else(|| js_sys::TypeError::new("Element must be a textarea"))?;
|
||||
|
||||
let value = textarea.value();
|
||||
|
||||
let scroll_height = textarea.scroll_height();
|
||||
let scrolled_to_bottom = scroll_height - textarea.scroll_top() == textarea.client_height();
|
||||
|
||||
textarea.set_value(&format!("{}{}", value, text));
|
||||
|
||||
if scrolled_to_bottom {
|
||||
textarea.scroll_with_x_and_y(0.0, scroll_height.into());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user