on master help sign in
Merge pull request #21 from fitzgen/js-api

JS API

commit37dc79bc7e26186f84740e40ba512dc4fc8c451d authorNick Fitzgerald <fitzgen@gmail.com> dateThu 28 Feb 2019, 13:03 (8 years ago) parent00a42e323b4a66
12 files changed+812−66
Cargo.lock+84−59 Cargo.toml+3 crates/js-api/Cargo.toml+15 crates/js-api/src/lib.rs+332 examples/js-component/Cargo.toml+26 examples/js-component/README.md+23 examples/js-component/greeting.js+41 examples/js-component/index.html+14 examples/js-component/src/lib.rs+67 src/builder.rs+43−7 tests/web/js_api.rs+163 tests/web/main.rs+1
Cargo.lock+84−59
@@ -66,7 +66,7 @@ version = "0.1.5"
6666source = "registry+https://github.com/rust-lang/crates.io-index"
6767dependencies = [
6868 "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
69− "wasm-bindgen 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
69+ "wasm-bindgen 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
7070]
7171
7272[[package]]
@@ -75,7 +75,7 @@ version = "0.1.2"
7575source = "registry+https://github.com/rust-lang/crates.io-index"
7676dependencies = [
7777 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
78− "web-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
78+ "web-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
7979]
8080
8181[[package]]
@@ -85,13 +85,14 @@ dependencies = [
8585 "bumpalo 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
8686 "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
8787 "console_log 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
88+ "dodrio-js-api 0.1.0",
8889 "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
89− "js-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
90+ "js-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
9091 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
91− "wasm-bindgen 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
92− "wasm-bindgen-futures 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
93− "wasm-bindgen-test 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
94− "web-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
92+ "wasm-bindgen 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
93+ "wasm-bindgen-futures 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
94+ "wasm-bindgen-test 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
95+ "web-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
9596]
9697
9798[[package]]
@@ -102,9 +103,9 @@ dependencies = [
102103 "console_log 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
103104 "dodrio 0.1.0",
104105 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
105− "wasm-bindgen 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
106− "wasm-bindgen-test 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
107− "web-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
106+ "wasm-bindgen 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
107+ "wasm-bindgen-test 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
108+ "web-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
108109]
109110
110111[[package]]
@@ -113,9 +114,9 @@ version = "0.1.0"
113114dependencies = [
114115 "console_error_panic_hook 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
115116 "dodrio 0.1.0",
116− "wasm-bindgen 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
117− "wasm-bindgen-test 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
118− "web-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
117+ "wasm-bindgen 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
118+ "wasm-bindgen-test 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
119+ "web-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
119120]
120121
121122[[package]]
@@ -124,9 +125,33 @@ version = "0.1.0"
124125dependencies = [
125126 "console_error_panic_hook 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
126127 "dodrio 0.1.0",
127− "wasm-bindgen 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
128− "wasm-bindgen-test 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
129− "web-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
128+ "wasm-bindgen 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
129+ "wasm-bindgen-test 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
130+ "web-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
131+]
132+
133+[[package]]
134+name = "dodrio-js-api"
135+version = "0.1.0"
136+dependencies = [
137+ "dodrio 0.1.0",
138+ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
139+ "js-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
140+ "wasm-bindgen 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
141+ "wasm-bindgen-futures 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
142+ "wasm-bindgen-test 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
143+]
144+
145+[[package]]
146+name = "dodrio-js-component"
147+version = "0.1.0"
148+dependencies = [
149+ "console_error_panic_hook 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
150+ "dodrio 0.1.0",
151+ "dodrio-js-api 0.1.0",
152+ "js-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
153+ "wasm-bindgen 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
154+ "web-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
130155]
131156
132157[[package]]
@@ -138,14 +163,14 @@ dependencies = [
138163 "console_log 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
139164 "dodrio 0.1.0",
140165 "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
141− "js-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
166+ "js-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
142167 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
143168 "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
144169 "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
145− "wasm-bindgen 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
146− "wasm-bindgen-futures 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
147− "wasm-bindgen-test 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
148− "web-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
170+ "wasm-bindgen 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
171+ "wasm-bindgen-futures 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
172+ "wasm-bindgen-test 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
173+ "web-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
149174]
150175
151176[[package]]
@@ -208,10 +233,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
208233
209234[[package]]
210235name = "js-sys"
211−version = "0.3.13"
236+version = "0.3.14"
212237source = "registry+https://github.com/rust-lang/crates.io-index"
213238dependencies = [
214− "wasm-bindgen 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
239+ "wasm-bindgen 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
215240]
216241
217242[[package]]
@@ -422,15 +447,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
422447
423448[[package]]
424449name = "wasm-bindgen"
425−version = "0.2.36"
450+version = "0.2.37"
426451source = "registry+https://github.com/rust-lang/crates.io-index"
427452dependencies = [
428− "wasm-bindgen-macro 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
453+ "wasm-bindgen-macro 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
429454]
430455
431456[[package]]
432457name = "wasm-bindgen-backend"
433−version = "0.2.36"
458+version = "0.2.37"
434459source = "registry+https://github.com/rust-lang/crates.io-index"
435460dependencies = [
436461 "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -438,62 +463,62 @@ dependencies = [
438463 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
439464 "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
440465 "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
441− "wasm-bindgen-shared 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
466+ "wasm-bindgen-shared 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
442467]
443468
444469[[package]]
445470name = "wasm-bindgen-futures"
446−version = "0.3.13"
471+version = "0.3.14"
447472source = "registry+https://github.com/rust-lang/crates.io-index"
448473dependencies = [
449474 "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
450− "js-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
451− "wasm-bindgen 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
475+ "js-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
476+ "wasm-bindgen 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
452477]
453478
454479[[package]]
455480name = "wasm-bindgen-macro"
456−version = "0.2.36"
481+version = "0.2.37"
457482source = "registry+https://github.com/rust-lang/crates.io-index"
458483dependencies = [
459484 "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
460− "wasm-bindgen-macro-support 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
485+ "wasm-bindgen-macro-support 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
461486]
462487
463488[[package]]
464489name = "wasm-bindgen-macro-support"
465−version = "0.2.36"
490+version = "0.2.37"
466491source = "registry+https://github.com/rust-lang/crates.io-index"
467492dependencies = [
468493 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
469494 "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
470495 "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
471− "wasm-bindgen-backend 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
472− "wasm-bindgen-shared 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
496+ "wasm-bindgen-backend 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
497+ "wasm-bindgen-shared 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
473498]
474499
475500[[package]]
476501name = "wasm-bindgen-shared"
477−version = "0.2.36"
502+version = "0.2.37"
478503source = "registry+https://github.com/rust-lang/crates.io-index"
479504
480505[[package]]
481506name = "wasm-bindgen-test"
482−version = "0.2.36"
507+version = "0.2.37"
483508source = "registry+https://github.com/rust-lang/crates.io-index"
484509dependencies = [
485510 "console_error_panic_hook 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
486511 "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
487− "js-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
512+ "js-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
488513 "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
489− "wasm-bindgen 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
490− "wasm-bindgen-futures 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
491− "wasm-bindgen-test-macro 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
514+ "wasm-bindgen 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
515+ "wasm-bindgen-futures 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
516+ "wasm-bindgen-test-macro 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
492517]
493518
494519[[package]]
495520name = "wasm-bindgen-test-macro"
496−version = "0.2.36"
521+version = "0.2.37"
497522source = "registry+https://github.com/rust-lang/crates.io-index"
498523dependencies = [
499524 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -502,7 +527,7 @@ dependencies = [
502527
503528[[package]]
504529name = "wasm-bindgen-webidl"
505−version = "0.2.30"
530+version = "0.2.31"
506531source = "registry+https://github.com/rust-lang/crates.io-index"
507532dependencies = [
508533 "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -511,21 +536,21 @@ dependencies = [
511536 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
512537 "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
513538 "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
514− "wasm-bindgen-backend 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
539+ "wasm-bindgen-backend 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
515540 "weedle 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
516541]
517542
518543[[package]]
519544name = "web-sys"
520−version = "0.3.13"
545+version = "0.3.14"
521546source = "registry+https://github.com/rust-lang/crates.io-index"
522547dependencies = [
523548 "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
524549 "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
525− "js-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
550+ "js-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
526551 "sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
527− "wasm-bindgen 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
528− "wasm-bindgen-webidl 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
552+ "wasm-bindgen 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
553+ "wasm-bindgen-webidl 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
529554]
530555
531556[[package]]
@@ -590,7 +615,7 @@ dependencies = [
590615"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
591616"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
592617"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
593−"checksum js-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9639a5b9944fc99bc02992f25ac25f8617e81860b0b31f61eb15a1f4fe4b39f3"
618+"checksum js-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4dbd938475b240c421c270c2c0dd0f9acc3642e02d7419afd37587a34cd04e40"
594619"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
595620"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047"
596621"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
@@ -620,16 +645,16 @@ dependencies = [
620645"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
621646"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
622647"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
623−"checksum wasm-bindgen 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a07590bf415481c15debf0fb459e4ee7bc5f7063b3adf450cea87cfc5451ff"
624−"checksum wasm-bindgen-backend 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "93c3e81841784d407e9ce7a047a88f093861b70584de6ae9072d1c6985de62b8"
625−"checksum wasm-bindgen-futures 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "09c886eacd2ea2662f02daa11bdd836778dfd97b5e7b5320bc7c6c7824835fd5"
626−"checksum wasm-bindgen-macro 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "702fae71b06d1c0527bf920cca51b75b2332aace0be6dc28abb50567f5f8e8d6"
627−"checksum wasm-bindgen-macro-support 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "0bb7feb04fa2c73d0c28579143c4104c7edbb84299f27bbc1dacc0dda3b56e19"
628−"checksum wasm-bindgen-shared 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "d191314b24a75d0798a22632aad4b18ed0098df42d0fcb0f759b394cf3bba02f"
629−"checksum wasm-bindgen-test 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "e403218d15f3a0be08ad984a4b97f4ce4d05f6d3df98ce6708c32f58cdd76286"
630−"checksum wasm-bindgen-test-macro 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "e1feb1af4e075b19eab744a8ed0da087b024ae79afc0b35e49c3ca9a4a1c327b"
631−"checksum wasm-bindgen-webidl 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "142b34c5209bd1b6562b9fee0e4bddd1bebf00717b6cb4ccc9f0a9b3cc9f5f03"
632−"checksum web-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "5cec4b17aece169adf93e8d05919e9ba7fb2156ebcf2280e6b5987868f287600"
648+"checksum wasm-bindgen 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)" = "2d85ba4917abb23ee7788330797a7cb5ac7e5e997cdc67fde6f2c8d02cc08db3"
649+"checksum wasm-bindgen-backend 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)" = "51f9c26bd7d30f21ce334785ec10c5ce10cba28313979d793b8dddede19da3a4"
650+"checksum wasm-bindgen-futures 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "25ee19bc252f9fbe54dadc21713b98d7a72f1d5f4b497ef9d9c112897131c3c6"
651+"checksum wasm-bindgen-macro 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)" = "316e6e568644bfa2009698217cec8f612a4e2cd7460b127f52573991c7ad9f53"
652+"checksum wasm-bindgen-macro-support 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)" = "29982ea76a7a35b5c3c052b6035abe9b84d8b6422d8881b68bd3472270a53eec"
653+"checksum wasm-bindgen-shared 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)" = "59305c5b959d51437636db05bac82de2b52da2c05157e38e018c0bd54cfd9bbf"
654+"checksum wasm-bindgen-test 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)" = "8e8b80ffed02a5971865b6e6769398c3581b234a47c301193c44e7766b1a7a64"
655+"checksum wasm-bindgen-test-macro 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)" = "92b66e86a39d33a9d7d46ae7a8c90e692ff4b7ecc0a69075a060511bc687562d"
656+"checksum wasm-bindgen-webidl 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "780c16a1a26d28695ac9af7176e11dbc3c188e6d0b3095ad51cc2d0e9e31fcc9"
657+"checksum web-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "02c19f8ab50a089f9d7c8070c191a919c85d10a4a37c5777a08e8f94ec12c0fc"
633658"checksum weedle 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "26a4c67f132386d965390b8a734d5d10adbcd30eb5cc74bd9229af8b83f10044"
634659"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
635660"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
Cargo.toml+3
@@ -26,6 +26,7 @@ features = [
2626
2727[dev-dependencies]
2828console_log = "0.1.2"
29+dodrio-js-api = { version = "=0.1.0", path = "./crates/js-api" }
2930log = "0.4.6"
3031wasm-bindgen-test = "0.2.36"
3132
@@ -46,8 +47,10 @@ opt-level = "s"
4647
4748[workspace]
4849members = [
50+ "./crates/js-api",
4951 "./examples/counter",
5052 "./examples/hello-world",
5153 "./examples/input-form",
54+ "./examples/js-component",
5255 "./examples/todomvc",
5356]
crates/js-api/Cargo.tomlnew file+15
@@ -0,0 +1,15 @@
1+[package]
2+name = "dodrio-js-api"
3+version = "0.1.0"
4+authors = ["Nick Fitzgerald <fitzgen@gmail.com>"]
5+edition = "2018"
6+
7+[dependencies]
8+dodrio = { version = "=0.1.0", path = "../.." }
9+wasm-bindgen = "0.2.37"
10+js-sys = "0.3.14"
11+wasm-bindgen-futures = "0.3.14"
12+futures = "0.1.25"
13+
14+[dev-dependencies]
15+wasm-bindgen-test = "0.2.37"
crates/js-api/src/lib.rsnew file+332
@@ -0,0 +1,332 @@
1+/*!
2+
3+Implementing `dodrio` render components with JavaScript.
4+
5+This crate provides a Rust type `JsRender` that wraps a JavaScript object with a
6+`render` method. `JsRender` implements `dodrio::Render` by calling its wrapped
7+object's `render` method to get a JavaScript virtual DOM represented as a tree
8+of JavaScript values. It then converts this tree of JavaScript values into
9+`dodrio`'s normal bump-allocated virtual DOM representation.
10+
11+This is likely much slower than rendering virtual DOMs directly into the bump
12+allocator from the Rust side of things! Additionally, the shape of the
13+JavaScript virtual DOM is a bit funky and unidiomatic. Keep in mind that this
14+crate exists as a proof of concept for integrating JavaScript components into
15+`dodrio` -- which is itself *also* experimental -- and so this crate definitely
16+has some rough edges.
17+
18+# Example
19+
20+Here is a JavaScript implementation of a rendering component:
21+
22+```javascript
23+class Greeting {
24+ constructor(who) {
25+ this.who = who;
26+ }
27+
28+ render() {
29+ return {
30+ tagName: "p",
31+ attributes: [
32+ {
33+ name: "class",
34+ value: "greeting",
35+ },
36+ ],
37+ listeners: [
38+ {
39+ on: "click",
40+ callback: this.onClick.bind(this),
41+ }
42+ ],
43+ children: [
44+ "Hello, ",
45+ {
46+ tagName: "strong",
47+ children: [this.who],
48+ }
49+ ],
50+ };
51+ }
52+
53+ async onClick(vdom, event) {
54+ // Be more excited!
55+ this.who += "!";
56+
57+ // Schedule a re-render.
58+ await vdom.render();
59+
60+ console.log("re-rendering finished!");
61+ }
62+}
63+```
64+
65+And here is a Rust rendering component that internally uses the JS rendering
66+component:
67+
68+```rust,no_run
69+use dodrio::bumpalo::Bump;
70+use dodrio::{Node, Render, Vdom};
71+use dodrio_js_api::JsRender;
72+use js_sys::Object;
73+use wasm_bindgen::prelude::*;
74+
75+#[wasm_bindgen]
76+extern {
77+ // Import the JS `Greeting` class.
78+ #[wasm_bindgen(extends = Object)]
79+ #[derive(Clone, Debug)]
80+ type Greeting;
81+
82+ // And the `Greeting` class's constructor.
83+ #[wasm_bindgen(constructor)]
84+ fn new(who: &str) -> Greeting;
85+}
86+
87+/// This is our Rust rendering component that wraps the JS rendering component.
88+pub struct GreetingViaJs {
89+ js: JsRender,
90+}
91+
92+impl GreetingViaJs {
93+ /// Create a new `GreetingViaJs`, which will internally create a new JS
94+ /// `Greeting`.
95+ pub fn new(who: &str) -> GreetingViaJs {
96+ let js = JsRender::new(Greeting::new(who));
97+ GreetingViaJs { js }
98+ }
99+}
100+
101+/// And finally the `Render` implementation! This adds a `<p>` element and some
102+/// text around whatever the inner JS `Greeting` component renders.
103+impl Render for GreetingViaJs {
104+ fn render<'a, 'bump>(&'a self, bump: &'bump Bump) -> Node<'bump>
105+ where
106+ 'a: 'bump,
107+ {
108+ use dodrio::builder::*;
109+ p(bump)
110+ .children([
111+ text("JavaScript says: "),
112+ self.js.render(bump),
113+ ])
114+ .finish()
115+ }
116+}
117+```
118+
119+ */
120+#![deny(missing_docs, missing_debug_implementations)]
121+
122+use dodrio::{
123+ builder,
124+ bumpalo::{self, Bump},
125+ Node, Render,
126+};
127+use futures::prelude::*;
128+use js_sys::{Object, Promise, Reflect};
129+use wasm_bindgen::prelude::*;
130+use wasm_bindgen::JsCast;
131+
132+#[wasm_bindgen]
133+extern "C" {
134+ /// A rendering component implemented in JavaScript.
135+ ///
136+ /// The rendering API is a bit duck-typed: any JS object with a `render`
137+ /// method that returns a virtual DOM as JS values with the right shape
138+ /// works.
139+ ///
140+ /// See `JsRender::new` for converting existing JS objects into `JsRender`s.
141+ #[derive(Debug, Clone)]
142+ pub type JsRender;
143+ #[wasm_bindgen(structural, method)]
144+ fn render(this: &JsRender) -> JsValue;
145+
146+ #[wasm_bindgen(extends = Object)]
147+ #[derive(Debug, Clone)]
148+ type Element;
149+ #[wasm_bindgen(structural, getter, method, js_name = tagName)]
150+ fn tag_name(this: &Element) -> String;
151+ #[wasm_bindgen(structural, getter, method)]
152+ fn listeners(this: &Element) -> js_sys::Array;
153+ #[wasm_bindgen(structural, getter, method)]
154+ fn attributes(this: &Element) -> js_sys::Array;
155+ #[wasm_bindgen(structural, getter, method)]
156+ fn children(this: &Element) -> js_sys::Array;
157+
158+ #[wasm_bindgen(extends = Object)]
159+ #[derive(Debug, Clone)]
160+ type Listener;
161+ #[wasm_bindgen(structural, getter, method)]
162+ fn on(this: &Listener) -> String;
163+ #[wasm_bindgen(structural, getter, method)]
164+ fn callback(this: &Listener) -> js_sys::Function;
165+
166+ #[wasm_bindgen(extends = Object)]
167+ #[derive(Debug, Clone)]
168+ type Attribute;
169+ #[wasm_bindgen(structural, getter, method)]
170+ fn name(this: &Attribute) -> String;
171+ #[wasm_bindgen(structural, getter, method)]
172+ fn value(this: &Attribute) -> String;
173+}
174+
175+/// A weak handle to a virtual DOM.
176+///
177+/// This is essentially the same as `dodrio::VdomWeak`, but exposed to
178+/// JavaScript.
179+#[wasm_bindgen]
180+#[derive(Clone, Debug)]
181+pub struct VdomWeak {
182+ inner: dodrio::VdomWeak,
183+}
184+
185+impl VdomWeak {
186+ fn new(inner: dodrio::VdomWeak) -> VdomWeak {
187+ VdomWeak { inner }
188+ }
189+}
190+
191+#[wasm_bindgen]
192+impl VdomWeak {
193+ /// Schedule re-rendering of the virtual DOM. A promise is returned that is
194+ /// resolved after the rendering has happened.
195+ pub fn render(&self) -> Promise {
196+ wasm_bindgen_futures::future_to_promise(
197+ self.inner.render().map(|_| JsValue::null()).map_err(|e| {
198+ let msg = e.to_string();
199+ js_sys::Error::new(&msg).into()
200+ }),
201+ )
202+ }
203+}
204+
205+impl JsRender {
206+ /// Convert a `js_sys::Object` into a `JsRender`.
207+ ///
208+ /// The given object must have a `render` method that conforms to the
209+ /// duck-typed virtual DOM interface which is described in the crate-level
210+ /// documentation.
211+ pub fn new<O>(object: O) -> JsRender
212+ where
213+ O: Into<Object>,
214+ {
215+ let object = object.into();
216+ debug_assert!(
217+ has_property(&object, "render"),
218+ "JS rendering components must have a `render` method"
219+ );
220+ object.unchecked_into::<JsRender>()
221+ }
222+}
223+
224+impl Render for JsRender {
225+ fn render<'a, 'bump>(&'a self, bump: &'bump Bump) -> Node<'bump>
226+ where
227+ 'a: 'bump,
228+ {
229+ create(bump, self.render())
230+ }
231+}
232+
233+fn has_property(obj: &Object, property: &str) -> bool {
234+ Reflect::has(obj, &property.into()).unwrap_or_default()
235+}
236+
237+fn create(bump: &Bump, val: JsValue) -> Node {
238+ if let Some(txt) = val.as_string() {
239+ let text = bumpalo::collections::String::from_str_in(&txt, bump);
240+ return builder::text(text.into_bump_str());
241+ }
242+
243+ let elem = val.unchecked_into::<Element>();
244+ debug_assert!(
245+ elem.is_instance_of::<Object>(),
246+ "JS render methods should only return strings for text nodes or objects for elements"
247+ );
248+ debug_assert!(
249+ has_property(&elem, "tagName"),
250+ "element objects returned by JS render methods must have a `tagName` property"
251+ );
252+
253+ let tag_name = elem.tag_name();
254+ let tag_name = bumpalo::collections::String::from_str_in(&tag_name, bump);
255+
256+ builder::ElementBuilder::new(bump, tag_name.into_bump_str())
257+ .listeners({
258+ let mut listeners =
259+ bumpalo::collections::Vec::new_in(bump);
260+ if has_property(&elem, "listeners") {
261+ let js_listeners = elem.listeners();
262+ listeners.reserve(js_listeners.length() as usize);
263+ js_listeners.for_each(&mut |listener, _index, _array| {
264+ let listener = listener.unchecked_into::<Listener>();
265+ debug_assert!(
266+ listener.is_instance_of::<Object>(),
267+ "listeners returned by JS render methods must be objects"
268+ );
269+ debug_assert!(
270+ has_property(&listener, "on"),
271+ "listener objects returned by JS render methods must have an `on` property"
272+ );
273+ debug_assert!(
274+ has_property(&listener, "callback"),
275+ "listener objects returned by JS render methods must have an `callback` property"
276+ );
277+ let on = listener.on();
278+ let on = bumpalo::collections::String::from_str_in(&on, bump);
279+ let callback = listener.callback();
280+ let elem = elem.clone();
281+ listeners.push(builder::on(bump, on.into_bump_str(), move |_root, vdom, event| {
282+ let vdom = VdomWeak::new(vdom);
283+ let vdom: JsValue = vdom.into();
284+ if let Err(e) = callback.call2(&elem, &vdom, &event) {
285+ wasm_bindgen::throw_val(e);
286+ }
287+ }));
288+ });
289+ }
290+ listeners
291+ })
292+ .attributes({
293+ let mut attributes = bumpalo::collections::Vec::new_in(bump);
294+ if has_property(&elem, "attributes") {
295+ let js_attributes = elem.attributes();
296+ attributes.reserve(js_attributes.length() as usize);
297+ js_attributes.for_each(&mut |attribute, _index, _array| {
298+ let attribute = attribute.unchecked_into::<Attribute>();
299+ debug_assert!(
300+ attribute.is_instance_of::<Object>(),
301+ "attributes returned by JS render methods must be objects"
302+ );
303+ debug_assert!(
304+ has_property(&attribute, "name"),
305+ "attribute objects returned by JS render methods must have a `name` property"
306+ );
307+ debug_assert!(
308+ has_property(&attribute, "value"),
309+ "attribute objects returned by JS render methods must have a `value` property"
310+ );
311+ let name = attribute.name();
312+ let name = bumpalo::collections::String::from_str_in(&name, bump);
313+ let value = attribute.value();
314+ let value = bumpalo::collections::String::from_str_in(&value, bump);
315+ attributes.push(builder::attr(name.into_bump_str(), value.into_bump_str()));
316+ });
317+ }
318+ attributes
319+ })
320+ .children({
321+ let mut children = bumpalo::collections::Vec::new_in(bump);
322+ if has_property(&elem, "children") {
323+ let js_children = elem.children();
324+ children.reserve(js_children.length() as usize);
325+ js_children.for_each(&mut |child, _index, _array| {
326+ children.push(create(bump, child));
327+ });
328+ }
329+ children
330+ })
331+ .finish()
332+}
examples/js-component/Cargo.tomlnew file+26
@@ -0,0 +1,26 @@
1+[package]
2+name = "dodrio-js-component"
3+version = "0.1.0"
4+authors = ["Nick Fitzgerald <fitzgen@gmail.com>"]
5+edition = "2018"
6+
7+[lib]
8+crate-type = ["cdylib"]
9+
10+[features]
11+
12+[dependencies]
13+dodrio = { path = "../.." }
14+dodrio-js-api = { path = "../../crates/js-api" }
15+wasm-bindgen = "0.2.36"
16+console_error_panic_hook = "0.1.5"
17+js-sys = "0.3.14"
18+
19+[dependencies.web-sys]
20+version = "0.3.13"
21+features = [
22+ "Document",
23+ "HtmlElement",
24+ "Node",
25+ "Window",
26+]
examples/js-component/README.mdnew file+23
@@ -0,0 +1,23 @@
1+# Defining a Rendering Component in JavaScript
2+
3+Heterogeneous Rust and JavaScript rendering component trees!
4+
5+## Source
6+
7+See `greeting.js` for the JavaScript code.
8+
9+See `src/lib.rs` for the Rust code.
10+
11+## Build
12+
13+```
14+wasm-pack build --target no-modules
15+```
16+
17+## Serve
18+
19+Use any HTTP server, for example:
20+
21+```
22+python -m SimpleHTTPServer
23+```
examples/js-component/greeting.jsnew file+41
@@ -0,0 +1,41 @@
1+// A rendering component defined in JavaScript!
2+class Greeting {
3+ constructor(who) {
4+ this.who = who;
5+ }
6+
7+ render() {
8+ return {
9+ tagName: "p",
10+ attributes: [
11+ {
12+ name: "class",
13+ value: "greeting",
14+ },
15+ ],
16+ listeners: [
17+ {
18+ on: "click",
19+ callback: this.onClick.bind(this),
20+ }
21+ ],
22+ children: [
23+ "Hello, ",
24+ {
25+ tagName: "strong",
26+ children: [this.who],
27+ }
28+ ],
29+ };
30+ }
31+
32+ async onClick(vdom, event) {
33+ // Be more excited!
34+ this.who += "!";
35+
36+ // Schedule a re-render.
37+ await vdom.render();
38+
39+ console.log("re-rendering finished!");
40+ }
41+}
examples/js-component/index.htmlnew file+14
@@ -0,0 +1,14 @@
1+<!DOCTYPE html>
2+<html>
3+ <head>
4+ <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
5+ <title>A JavaScript component!</title>
6+ </head>
7+ <body>
8+ <script src="greeting.js"></script>
9+ <script src="pkg/dodrio_js_component.js"></script>
10+ <script>
11+ wasm_bindgen("pkg/dodrio_js_component_bg.wasm");
12+ </script>
13+ </body>
14+</html>
examples/js-component/src/lib.rsnew file+67
@@ -0,0 +1,67 @@
1+use dodrio::bumpalo::Bump;
2+use dodrio::{Node, Render, Vdom};
3+use dodrio_js_api::JsRender;
4+use js_sys::Object;
5+use wasm_bindgen::prelude::*;
6+
7+#[wasm_bindgen]
8+extern "C" {
9+ // Import the JS `Greeting` class.
10+ #[wasm_bindgen(extends = Object)]
11+ #[derive(Clone, Debug)]
12+ type Greeting;
13+
14+ // And the `Greeting` class's constructor.
15+ #[wasm_bindgen(constructor)]
16+ fn new(who: &str) -> Greeting;
17+}
18+
19+/// This is our Rust rendering component that wraps the JS rendering component.
20+pub struct GreetingViaJs {
21+ js: JsRender,
22+}
23+
24+impl GreetingViaJs {
25+ /// Create a new `GreetingViaJs`, which will internally create a new JS
26+ /// `Greeting`.
27+ pub fn new(who: &str) -> GreetingViaJs {
28+ let js = JsRender::new(Greeting::new(who));
29+ GreetingViaJs { js }
30+ }
31+}
32+
33+/// Here's the `Render` implementation! This adds a `<p>` element and some text
34+/// around whatever the inner JS `Greeting` component renders.
35+impl Render for GreetingViaJs {
36+ fn render<'a, 'bump>(&'a self, bump: &'bump Bump) -> Node<'bump>
37+ where
38+ 'a: 'bump,
39+ {
40+ use dodrio::builder::*;
41+ p(bump)
42+ .children([text("JavaScript says: "), self.js.render(bump)])
43+ .finish()
44+ }
45+}
46+
47+/// Finally our main initialization function that kicks everything off!
48+#[wasm_bindgen(start)]
49+pub fn run() {
50+ // Set up the panic hook for debugging when things go wrong.
51+ console_error_panic_hook::set_once();
52+
53+ // Grab the document's `<body>`.
54+ let window = web_sys::window().unwrap_throw();
55+ let document = window.document().unwrap_throw();
56+ let body = document.body().unwrap_throw();
57+
58+ // Create a new `GreetingViaJs` render component.
59+ let component = GreetingViaJs::new("World");
60+
61+ // Create a virtual DOM and mount it and the `Hello` render component to the
62+ // `<body>`.
63+ let vdom = Vdom::new(body.as_ref(), component);
64+
65+ // Run the virtual DOM forever and don't unmount it.
66+ vdom.forget();
67+}
src/builder.rs+43−7
@@ -22,6 +22,48 @@ where
2222 children: Children,
2323}
2424
25+impl<'a>
26+ ElementBuilder<
27+ 'a,
28+ bumpalo::collections::Vec<'a, Listener<'a>>,
29+ bumpalo::collections::Vec<'a, Attribute<'a>>,
30+ bumpalo::collections::Vec<'a, Node<'a>>,
31+ >
32+{
33+ /// Create a new `ElementBuilder` for an element with the given tag name.
34+ ///
35+ /// In general, only use this constructor if the tag is dynamic (i.e. you
36+ /// might build a `<div>` or you might build a `<span>` and you don't know
37+ /// until runtime). Prefer using the tag-specific constructors instead:
38+ /// `div(bump)` or `span(bump)`, etc.
39+ ///
40+ /// # Example
41+ ///
42+ /// ```
43+ /// use dodrio::{builder::*, bumpalo::Bump};
44+ ///
45+ /// let b = Bump::new();
46+ ///
47+ /// let tag_name = if flip_coin() {
48+ /// "div"
49+ /// } else {
50+ /// "span"
51+ /// };
52+ ///
53+ /// let my_element_builder = ElementBuilder::new(&b, tag_name);
54+ /// # fn flip_coin() -> bool { true }
55+ /// ```
56+ pub fn new(bump: &'a Bump, tag_name: &'a str) -> Self {
57+ ElementBuilder {
58+ bump,
59+ tag_name,
60+ listeners: bumpalo::collections::Vec::new_in(bump),
61+ attributes: bumpalo::collections::Vec::new_in(bump),
62+ children: bumpalo::collections::Vec::new_in(bump),
63+ }
64+ }
65+}
66+
2567impl<'a, Listeners, Attributes, Children> ElementBuilder<'a, Listeners, Attributes, Children>
2668where
2769 Listeners: 'a + AsRef<[Listener<'a>]>,
@@ -312,13 +354,7 @@ macro_rules! builder_constructors {
312354 bumpalo::collections::Vec<'a, Attribute<'a>>,
313355 bumpalo::collections::Vec<'a, Node<'a>>,
314356 > {
315− ElementBuilder {
316− bump,
317− tag_name: stringify!($name),
318− listeners: bumpalo::collections::Vec::new_in(bump),
319− attributes: bumpalo::collections::Vec::new_in(bump),
320− children: bumpalo::collections::Vec::new_in(bump),
321− }
357+ ElementBuilder::new(bump, stringify!($name))
322358 }
323359 )*
324360 }
tests/web/js_api.rsnew file+163
@@ -0,0 +1,163 @@
1+use super::{assert_rendered, create_element, RenderFn};
2+use dodrio::{builder::*, bumpalo::Bump, Node, Render, Vdom};
3+use dodrio_js_api::JsRender;
4+use futures::prelude::*;
5+use futures::sync::oneshot;
6+use js_sys::Object;
7+use std::rc::Rc;
8+use wasm_bindgen::prelude::*;
9+use wasm_bindgen::JsCast;
10+use wasm_bindgen_test::*;
11+
12+pub struct WrapJs {
13+ inner: JsRender,
14+}
15+
16+impl WrapJs {
17+ pub fn new() -> (WrapJs, oneshot::Receiver<()>, Closure<FnMut()>) {
18+ let (sender, receiver) = oneshot::channel();
19+
20+ let on_after_render = Closure::wrap(Box::new({
21+ let mut sender = Some(sender);
22+ move || {
23+ sender
24+ .take()
25+ .expect_throw("on_after_render should only be called once")
26+ .send(())
27+ .expect_throw("receiver should not have been dropped");
28+ }
29+ }) as Box<FnMut()>);
30+
31+ let component = WrapJs {
32+ inner: JsRender::new(JsComponent::new(&on_after_render)),
33+ };
34+
35+ (component, receiver, on_after_render)
36+ }
37+}
38+
39+impl Render for WrapJs {
40+ fn render<'a, 'bump>(&'a self, bump: &'bump Bump) -> Node<'bump>
41+ where
42+ 'a: 'bump,
43+ {
44+ div(bump)
45+ .attr("class", "wrap-js")
46+ .children([self.inner.render(bump)])
47+ .finish()
48+ }
49+}
50+
51+#[wasm_bindgen]
52+extern "C" {
53+ #[wasm_bindgen(extends = Object)]
54+ #[derive(Clone, Debug)]
55+ type JsComponent;
56+
57+ #[wasm_bindgen(constructor)]
58+ fn new(on_after_render: &Closure<FnMut()>) -> JsComponent;
59+}
60+
61+fn eval_js_rendering_component() {
62+ use std::sync::Once;
63+ static EVAL: Once = Once::new();
64+ EVAL.call_once(|| {
65+ super::init_logging();
66+ js_sys::eval(
67+ r#"
68+ window.JsComponent = class JsComponent {
69+ constructor(onAfterRender) {
70+ this.count = 0;
71+ this.onAfterRender = onAfterRender;
72+ }
73+
74+ render() {
75+ return {
76+ tagName: "span",
77+ attributes: [{ name: "class", value: "js-component" }],
78+ listeners: [{ on: "click", callback: this.onClick.bind(this) }],
79+ children: [
80+ "Here is some plain text",
81+ {
82+ tagName: "b",
83+ children: ["...and here is some bold text"]
84+ },
85+ String(this.count),
86+ ]
87+ };
88+ }
89+
90+ async onClick(vdom, event) {
91+ this.count++;
92+ await vdom.render();
93+ this.onAfterRender();
94+ }
95+ };
96+ "#,
97+ )
98+ .expect_throw("should eval JS component OK");
99+ });
100+}
101+
102+#[wasm_bindgen_test(async)]
103+fn can_use_js_rendering_components() -> impl Future<Item = (), Error = JsValue> {
104+ eval_js_rendering_component();
105+
106+ let container = create_element("div");
107+ let (component, receiver, closure) = WrapJs::new();
108+
109+ let vdom = Rc::new(Vdom::new(&container, component));
110+ assert_rendered(
111+ &container,
112+ &RenderFn(|bump| {
113+ div(bump)
114+ .attr("class", "wrap-js")
115+ .children([span(bump)
116+ .attr("class", "js-component")
117+ .children([
118+ text("Here is some plain text"),
119+ b(bump)
120+ .children([text("...and here is some bold text")])
121+ .finish(),
122+ text("0"),
123+ ])
124+ .finish()])
125+ .finish()
126+ }),
127+ );
128+
129+ container
130+ .query_selector(".js-component")
131+ .expect_throw("should querySelector OK")
132+ .expect_throw("should find `.js-component` element OK")
133+ .dyn_into::<web_sys::HtmlElement>()
134+ .expect_throw("should be an `HTMLElement` object")
135+ .click();
136+
137+ receiver
138+ .map(move |_| {
139+ assert_rendered(
140+ &container,
141+ &RenderFn(|bump| {
142+ div(bump)
143+ .attr("class", "wrap-js")
144+ .children([span(bump)
145+ .attr("class", "js-component")
146+ .children([
147+ text("Here is some plain text"),
148+ b(bump)
149+ .children([text("...and here is some bold text")])
150+ .finish(),
151+ text("1"),
152+ ])
153+ .finish()])
154+ .finish()
155+ }),
156+ );
157+
158+ drop(vdom);
159+ drop(container);
160+ drop(closure);
161+ })
162+ .map_err(|e| e.to_string().into())
163+}
tests/web/main.rs+1
@@ -15,6 +15,7 @@ wasm_bindgen_test_configure!(run_in_browser);
1515
1616pub mod cached;
1717pub mod events;
18+pub mod js_api;
1819pub mod render;
1920
2021pub fn window() -> web_sys::Window {