Skip to content

Commit 8e6ac82

Browse files
committed
Merge branch 'jstarry-update-yew'
2 parents 2cb33e4 + 37c0945 commit 8e6ac82

File tree

13 files changed

+521
-875
lines changed

13 files changed

+521
-875
lines changed
File renamed without changes.

frameworks/keyed/yew/Cargo.toml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
[package]
2+
name = "js-framework-benchmark-yew"
3+
version = "1.0.0"
4+
authors = ["Isamu Mogi <[email protected]>"]
5+
edition = "2018"
6+
7+
[lib]
8+
crate-type = ["cdylib"]
9+
10+
[dependencies]
11+
rand = { version = "0.7.3", features = ["wasm-bindgen", "small_rng"] }
12+
wasm-bindgen = "0.2.62"
13+
yew = "0.17.2"
14+
15+
[profile.release]
16+
lto = true
17+
codegen-units = 1
18+
panic = "abort"
19+
20+
[package.metadata.wasm-pack.profile.release]
21+
wasm-opt = ['-O4']
File renamed without changes.

frameworks/non-keyed/yew/index.html renamed to frameworks/keyed/yew/bundled-dist/index.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
<base href="bundled-dist/"></base>
88
</head>
99
<body>
10+
<div id='main'></div>
1011
<script type="module">
11-
import init from "./js_framework_benchmark_yew.js"
12-
init()
12+
import init from './js-framework-benchmark-yew.js';
13+
init('./js-framework-benchmark-yew_bg.wasm');
1314
</script>
1415
</body>
1516
</html>

frameworks/non-keyed/yew/bundled-dist/js_framework_benchmark_yew.js renamed to frameworks/keyed/yew/bundled-dist/js-framework-benchmark-yew.js

Lines changed: 162 additions & 158 deletions
Large diffs are not rendered by default.
Binary file not shown.

frameworks/keyed/yew/index.html

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Yew</title>
6+
<link href="/css/currentStyle.css" rel="stylesheet"/>
7+
<base href="bundled-dist/"></base>
8+
</head>
9+
<body>
10+
<div id='main'></div>
11+
<script type="module">
12+
import init from './js-framework-benchmark-yew.js';
13+
init('./js-framework-benchmark-yew_bg.wasm');
14+
</script>
15+
</body>
16+
</html>

frameworks/non-keyed/yew/package.json renamed to frameworks/keyed/yew/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
"description": "Benchmark for Yew",
55
"license": "ISC",
66
"js-framework-benchmark": {
7-
"frameworkVersion": "0.7.0"
7+
"frameworkVersion": "0.17.2"
88
},
99
"scripts": {
1010
"build-prod": "echo This is a no-op. && echo Due to heavy dependencies, the generated javascript is already provided. && echo If you really want to rebuild from source use: && echo npm run build-prod-force",
11-
"build-prod-force": "rimraf bundled-dist target/deploy && rustup toolchain install nightly && rustup override set nightly && rustup target add wasm32-unknown-unknown && cargo install -f wasm-pack && wasm-pack build --release --target web && cpr pkg bundled-dist"
11+
"build-prod-force": "rustup target add wasm32-unknown-unknown && cargo install wasm-pack && rimraf bundled-dist && wasm-pack build --release --target web --no-typescript --out-name js-framework-benchmark-yew --out-dir bundled-dist && cpr index.html bundled-dist/index.html && (cd bundled-dist && rimraf .gitignore README.md package.json)"
1212
},
1313
"repository": {
1414
"type": "git",

frameworks/keyed/yew/src/lib.rs

Lines changed: 317 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
#![recursion_limit = "1024"]
2+
3+
use rand::prelude::*;
4+
use std::cmp::min;
5+
use wasm_bindgen::prelude::wasm_bindgen;
6+
use yew::prelude::*;
7+
use yew::web_sys::window;
8+
9+
static ADJECTIVES: &[&str] = &[
10+
"pretty",
11+
"large",
12+
"big",
13+
"small",
14+
"tall",
15+
"short",
16+
"long",
17+
"handsome",
18+
"plain",
19+
"quaint",
20+
"clean",
21+
"elegant",
22+
"easy",
23+
"angry",
24+
"crazy",
25+
"helpful",
26+
"mushy",
27+
"odd",
28+
"unsightly",
29+
"adorable",
30+
"important",
31+
"inexpensive",
32+
"cheap",
33+
"expensive",
34+
"fancy",
35+
];
36+
37+
static COLOURS: &[&str] = &[
38+
"red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black",
39+
"orange",
40+
];
41+
42+
static NOUNS: &[&str] = &[
43+
"table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger",
44+
"pizza", "mouse", "keyboard",
45+
];
46+
47+
#[derive(Clone, PartialEq)]
48+
struct RowData {
49+
id: usize,
50+
label: String,
51+
}
52+
53+
impl RowData {
54+
fn new(id: usize, rng: &mut SmallRng) -> Self {
55+
let mut label = String::new();
56+
label.push_str(ADJECTIVES.choose(rng).unwrap());
57+
label.push(' ');
58+
label.push_str(COLOURS.choose(rng).unwrap());
59+
label.push(' ');
60+
label.push_str(NOUNS.choose(rng).unwrap());
61+
62+
Self { id, label }
63+
}
64+
}
65+
66+
struct Model {
67+
rows: Vec<RowData>,
68+
next_id: usize,
69+
selected_id: Option<usize>,
70+
rng: SmallRng,
71+
link: ComponentLink<Self>,
72+
on_select: Callback<usize>,
73+
on_remove: Callback<usize>,
74+
}
75+
76+
enum Msg {
77+
Run(usize),
78+
Add(usize),
79+
Update(usize),
80+
Clear,
81+
Swap,
82+
Remove(usize),
83+
Select(usize),
84+
}
85+
86+
impl Component for Model {
87+
type Message = Msg;
88+
type Properties = ();
89+
90+
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
91+
Model {
92+
rows: Vec::new(),
93+
next_id: 1,
94+
selected_id: None,
95+
rng: SmallRng::from_entropy(),
96+
on_select: link.callback(|id| Msg::Select(id)),
97+
on_remove: link.callback(|id| Msg::Remove(id)),
98+
link,
99+
}
100+
}
101+
102+
fn change(&mut self, _: ()) -> ShouldRender {
103+
false
104+
}
105+
106+
fn update(&mut self, msg: Self::Message) -> ShouldRender {
107+
match msg {
108+
Msg::Run(amount) => {
109+
let rng = &mut self.rng;
110+
let next_id = self.next_id;
111+
let update_amount = min(amount, self.rows.len());
112+
for index in 0..update_amount {
113+
self.rows[index] = RowData::new(next_id + index, rng);
114+
}
115+
self.rows.extend(
116+
(update_amount..amount).map(|index| RowData::new(next_id + index, rng)),
117+
);
118+
self.next_id += amount;
119+
}
120+
Msg::Add(amount) => {
121+
let rng = &mut self.rng;
122+
let next_id = self.next_id;
123+
self.rows
124+
.extend((0..amount).map(|index| RowData::new(next_id + index, rng)));
125+
self.next_id += amount;
126+
}
127+
Msg::Update(step) => {
128+
for index in (0..self.rows.len()).step_by(step) {
129+
self.rows[index].label += " !!!";
130+
}
131+
}
132+
Msg::Clear => {
133+
self.rows.clear();
134+
}
135+
Msg::Swap => {
136+
if self.rows.len() > 998 {
137+
self.rows.swap(1, 998);
138+
}
139+
}
140+
Msg::Remove(id) => {
141+
if let Some(index) = self.rows.iter().position(|row| row.id == id) {
142+
self.rows.remove(index);
143+
}
144+
}
145+
Msg::Select(id) => {
146+
self.selected_id = Some(id);
147+
}
148+
}
149+
true
150+
}
151+
152+
fn view(&self) -> Html {
153+
let rows: Html = self
154+
.rows
155+
.iter()
156+
.map(|row| {
157+
html! {
158+
<Row key=row.id
159+
data=row.clone()
160+
selected=self.selected_id == Some(row.id)
161+
on_select=self.on_select.clone()
162+
on_remove=self.on_remove.clone() />
163+
}
164+
})
165+
.collect();
166+
167+
html! {
168+
<div class="container">
169+
<Jumbotron link=self.link.clone() />
170+
<table class="table table-hover table-striped test-data">
171+
<tbody id="tbody">
172+
{ rows }
173+
</tbody>
174+
</table>
175+
<span class="preloadicon glyphicon glyphicon-remove" aria-hidden="true"></span>
176+
</div>
177+
}
178+
}
179+
}
180+
181+
#[derive(Properties, Clone)]
182+
struct JumbotronProps {
183+
link: ComponentLink<Model>,
184+
}
185+
186+
struct Jumbotron {
187+
link: ComponentLink<Model>,
188+
}
189+
190+
impl Component for Jumbotron {
191+
type Properties = JumbotronProps;
192+
type Message = ();
193+
194+
fn create(props: Self::Properties, _: ComponentLink<Self>) -> Self {
195+
Self { link: props.link }
196+
}
197+
198+
fn change(&mut self, _: Self::Properties) -> ShouldRender {
199+
false
200+
}
201+
202+
fn update(&mut self, _: Self::Message) -> ShouldRender {
203+
false
204+
}
205+
206+
fn view(&self) -> Html {
207+
html! {
208+
<div class="jumbotron">
209+
<div class="row">
210+
<div class="col-md-6">
211+
<h1>{ "Yew" }</h1>
212+
</div>
213+
<div class="col-md-6">
214+
<div class="row">
215+
<div class="col-sm-6 smallpad">
216+
<button type="button" id="run" class="btn btn-primary btn-block" onclick=self.link.callback(|_| Msg::Run(1_000))>{ "Create 1,000 rows" }</button>
217+
</div>
218+
<div class="col-sm-6 smallpad">
219+
<button type="button" class="btn btn-primary btn-block" onclick=self.link.callback(|_| Msg::Run(10_000)) id="runlots">{ "Create 10,000 rows" }</button>
220+
</div>
221+
<div class="col-sm-6 smallpad">
222+
<button type="button" class="btn btn-primary btn-block" onclick=self.link.callback(|_| Msg::Add(1_000)) id="add">{ "Append 1,000 rows" }</button>
223+
</div>
224+
<div class="col-sm-6 smallpad">
225+
<button type="button" class="btn btn-primary btn-block" onclick=self.link.callback(|_| Msg::Update(10)) id="update">{ "Update every 10th row" }</button>
226+
</div>
227+
<div class="col-sm-6 smallpad">
228+
<button type="button" class="btn btn-primary btn-block" onclick=self.link.callback(|_| Msg::Clear) id="clear">{ "Clear" }</button>
229+
</div>
230+
<div class="col-sm-6 smallpad">
231+
<button type="button" class="btn btn-primary btn-block" onclick=self.link.callback(|_| Msg::Swap) id="swaprows">{ "Swap Rows" }</button>
232+
</div>
233+
</div>
234+
</div>
235+
</div>
236+
</div>
237+
}
238+
}
239+
}
240+
241+
#[derive(Properties, Clone, PartialEq)]
242+
struct RowProps {
243+
on_select: Callback<usize>,
244+
on_remove: Callback<usize>,
245+
selected: bool,
246+
data: RowData,
247+
}
248+
249+
struct RowState {
250+
on_select: Callback<MouseEvent>,
251+
on_remove: Callback<MouseEvent>,
252+
}
253+
254+
struct Row {
255+
state: RowState,
256+
props: RowProps,
257+
}
258+
259+
impl RowState {
260+
fn from_props(props: &RowProps) -> Self {
261+
let id = props.data.id;
262+
Self {
263+
on_select: props.on_select.reform(move |_| id),
264+
on_remove: props.on_remove.reform(move |_| id),
265+
}
266+
}
267+
}
268+
269+
impl Component for Row {
270+
type Message = ();
271+
type Properties = RowProps;
272+
273+
fn create(props: Self::Properties, _: ComponentLink<Self>) -> Self {
274+
Self {
275+
state: RowState::from_props(&props),
276+
props,
277+
}
278+
}
279+
280+
fn change(&mut self, props: RowProps) -> ShouldRender {
281+
if self.props != props {
282+
self.state = RowState::from_props(&props);
283+
self.props = props;
284+
true
285+
} else {
286+
false
287+
}
288+
}
289+
290+
fn update(&mut self, _: ()) -> ShouldRender {
291+
false
292+
}
293+
294+
fn view(&self) -> Html {
295+
html! {
296+
<tr class=if self.props.selected { "danger" } else { "" }>
297+
<td class="col-md-1">{ self.props.data.id }</td>
298+
<td class="col-md-4" onclick=self.state.on_select.clone()>
299+
<a class="lbl">{ self.props.data.label.clone() }</a>
300+
</td>
301+
<td class="col-md-1">
302+
<a class="remove" onclick=self.state.on_remove.clone()>
303+
<span class="glyphicon glyphicon-remove remove" aria-hidden="true"></span>
304+
</a>
305+
</td>
306+
<td class="col-md-6"></td>
307+
</tr>
308+
}
309+
}
310+
}
311+
312+
#[wasm_bindgen(start)]
313+
pub fn start() {
314+
let document = window().unwrap().document().unwrap();
315+
let mount_el = document.query_selector("#main").unwrap().unwrap();
316+
App::<Model>::new().mount(mount_el);
317+
}

0 commit comments

Comments
 (0)